aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--h-client/hlibrary.py474
1 files changed, 474 insertions, 0 deletions
diff --git a/h-client/hlibrary.py b/h-client/hlibrary.py
new file mode 100644
index 0000000..6e8f66f
--- /dev/null
+++ b/h-client/hlibrary.py
@@ -0,0 +1,474 @@
+# -*- coding: utf-8 -*-
+# hlibrary, a python library to manage the database of an h-source node
+# Copyright (C) 2011 Antonio Gallo
+#
+#
+# hlibrary 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.
+#
+# hlibrary 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 hlibrary. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import string
+import re
+import sys
+import pycurl
+import urllib
+from xml.dom import minidom
+
+
+
+class Device(object):
+
+ _allowedDistros = {
+ 'blag_90001' : 'BLAG 90001',
+ 'blag_120000' : 'BLAG 120000',
+ 'dragora_1_1' : 'Dragora 1.1',
+ 'dragora_2_0' : 'Dragora 2.0 Ardi',
+ 'dynebolic_2_5_2' : 'Dynebolic 2.5.2 DHORUBA',
+ 'gnewsense_2_3' : 'gNewSense 2.3 Deltah',
+ 'gnewsense_3_0' : 'gNewSense 3.0 Metad',
+ 'musix_2_0' : 'Musix GNU+Linux 2.0 R0',
+ 'trisquel_3_5' : 'Trisquel 3.5 Awen',
+ 'trisquel_4_0' : 'Trisquel 4.0 Taranis',
+ 'trisquel_4_5' : 'Trisquel 4.5 Slaine',
+ 'ututo_xs_2009' : 'UTUTO XS 2009',
+ 'ututo_xs_2010' : 'UTUTO XS 2010',
+ 'venenux_0_8' : 'VENENUX 0.8',
+ 'venenux_0_8_2' : 'VENENUX-EC 0.8.2'
+ }
+
+ _status = True
+
+ errors = []
+
+ def __init__(self):
+ self._post = {}
+ self._type = None
+ self._vendor = None
+ self._model = None
+ self._kernel = None
+ self._distributions = None
+ self._interface = 'not-specified'
+ self._year = 'not-specified'
+ self._vendorId = None
+ self._productId = None
+ self._howItWorks = None
+ self._driver = ''
+ self._description = None
+
+ def setPost(self):
+ self._post['model'] = self._model;
+ self._post['kernel'] = self._kernel;
+ self._post['distribution'] = self._distributions;
+ self._post['comm_year'] = self._year;
+ self._post['pci_id'] = self._vendorId + ':' + self._productId;
+ self._post['interface'] = self._interface;
+ self._post['description'] = self._description;
+ self._post['driver'] = self._driver;
+
+
+ def getType(self):
+ return self._type
+
+ def getVendor(self):
+ return self._vendor
+
+ def getModel(self):
+ return self._model
+
+ def getKernel(self):
+ return self._kernel
+
+ def getDistributions(self):
+ return self._distributions
+
+ def getInterface(self):
+ return self._interface
+
+ def getYear(self):
+ return self._year
+
+ def getVendorId(self):
+ return self._vendorId
+
+ def getProductId(self):
+ return self._productId
+
+ def getHowItWorks(self):
+ return self._howItWorks
+
+ def getDriver(self):
+ return self._driver
+
+ def getDescription(self):
+ return self._description
+
+ def setType(self,ttype):
+ self._type = ttype
+
+ def setVendor(self,vendor):
+ self._vendor = vendor
+
+ def setModel(self,model):
+ self._model = model
+
+ def setKernel(self,kernel):
+ self._kernel = kernel
+
+ def setDistributions(self,distributions):
+ distArray = distributions.split(',');
+
+ allowedDistKeys = self._allowedDistros.keys()
+
+ for dist in distArray:
+ if dist not in allowedDistKeys:
+ self._status = False
+ self.errors.append('distribution ' + dist + ' not allowed')
+
+ self._distributions = distributions
+
+ def setInterface(self,interface):
+ self._interface = interface
+
+ def setYear(self,year):
+ self._year = year
+
+ def setVendorId(self,vendorId):
+ self._vendorId = vendorId
+
+ def setProductId(self,productId):
+ self._productId = productId
+
+ def setHowItWorks(self,howItWorks):
+ self._howItWorks = howItWorks
+
+ def setDriver(self,driver):
+ self._driver = driver
+
+ def setDescription(self,description):
+ self._description = description
+
+ def getStatus(self):
+ return self._status
+
+ def getPost(self):
+ return self._post
+
+class Videocard(Device):
+
+ def __init__(self):
+ super(Videocard, self).__init__()
+ self._type = 'videocard';
+
+ def setPost(self):
+ super(Videocard, self).setPost()
+ self._post['video_card_works'] = self._howItWorks
+
+class Wifi(Device):
+
+ def __init__(self):
+ super(Wifi, self).__init__()
+ self._type = 'wifi';
+
+ def setPost(self):
+ super(Wifi, self).setPost()
+ self._post['wifi_works'] = self._howItWorks
+
+class Soundcard(Device):
+
+ def __init__(self):
+ super(Soundcard, self).__init__()
+ self._type = 'soundcard';
+
+ def setPost(self):
+ super(Soundcard, self).setPost()
+ self._post['sound_card_works'] = self._howItWorks
+
+
+#class to carry out http requests by means of pycurl
+class Mycurl:
+
+ _post = None
+
+ #set the domain
+ def __init__(self,domain):
+ self.contents = ''
+ self.domain = domain
+ #check if the trailing slash is present
+ if self.domain[len(self.domain)-1] != '/':
+ self.domain += '/'
+
+ def setPost(self,post):
+ self._post = post
+
+ def body_callback(self, buf):
+ self.contents = self.contents + buf
+
+ def perform(self,requestUri = ''):
+
+ self.url = self.domain + requestUri;
+ #print self.url
+ self.contents = ''
+ c = pycurl.Curl()
+ c.setopt(c.URL, self.url)
+ c.setopt(pycurl.COOKIEFILE, 'tmp/cookies.txt')
+ c.setopt(pycurl.COOKIEJAR, 'tmp/cookies.txt')
+ if self._post != None:
+ c.setopt(c.POSTFIELDS, urllib.urlencode(self._post))
+ c.setopt(c.WRITEFUNCTION, self.body_callback)
+ c.perform()
+ c.close()
+
+class Client:
+
+ devices = {}
+
+ _status = True
+ errors = []
+
+ _types = {
+ '0403' : {
+ 'type' : 'soundcard',
+ 'controller': 'soundcards'
+ },
+ '0280' : {
+ 'type' : 'wifi',
+ 'controller': 'wifi'
+ },
+ '0300' : {
+ 'type' : 'videocard',
+ 'controller': 'videocards'
+ }
+ }
+
+ def __init__(self,url):
+ self.request = Mycurl(url)
+
+ #get the type from the Class id
+ def getType(self, Class):
+ Classes = self._types.keys()
+ if Class in Classes:
+ return self._types[Class]['type']
+ return None
+
+ #get the controller from the Class id
+ def getController(self, Class):
+ Classes = self._types.keys()
+ if Class in Classes:
+ return self._types[Class]['controller']
+ return None
+
+ #return a device object
+ def getObject(self,Class):
+ if Class == '0403':
+ return Soundcard()
+ elif Class == '0280':
+ return Wifi()
+ elif Class == '0300':
+ return Videocard()
+ else:
+ return None
+
+ #get the system kernel
+ def getKernel(self):
+ if not os.system('uname -r > tmp/temp'):
+ f = open('tmp/temp','r')
+ row = f.readline().replace("\n","")
+ f.close();
+ return row
+ else:
+ self._status = False
+ self.errors.append('tmp folder not writable')
+
+ #log in
+ def login(self, username, password):
+ self.request.setPost({'username' : username, 'password' : password})
+ self.request.perform('users/login/en')
+ self.request.setPost(None)
+
+ #log out
+ def logout(self):
+ self.request.perform('users/logout/en')
+
+ #get info about the user logged
+ def getUserInfo(self):
+ self.request.perform('users/info/en')
+ xmldoc = minidom.parseString(self.request.contents)
+ status = modelName = xmldoc.getElementsByTagName("status")[0].childNodes[0].data
+
+ username = ''
+ token = ''
+ groups = ''
+
+ if status == 'logged':
+ username = modelName = xmldoc.getElementsByTagName("username")[0].childNodes[0].data
+ token = modelName = xmldoc.getElementsByTagName("token")[0].childNodes[0].data
+ groups = modelName = xmldoc.getElementsByTagName("groups")[0].childNodes[0].data
+
+ return {'status':status,'username':username,'token':token,'groups':groups}
+
+ #return True if the user is logged, else return False
+ def isLogged(self):
+ info = self.getUserInfo()
+
+ if info['status'] == 'logged':
+ return True
+
+ return False
+
+ def createDevices(self):
+ if not os.system('lspci -vmmnn > tmp/temp'):
+ f = open('tmp/temp','r')
+
+ while 1:
+ row = f.readline()
+
+ if not row:
+ break
+
+ #get the slot
+ if row.find('Slot') != -1:
+
+ #get the class
+ row = f.readline().replace("\n","")
+ if row:
+ cl = re.match('Class\:(.*)\[(.*)\]',row,re.I)
+ if cl:
+ #get the object
+ dev = self.getObject(cl.group(2))
+ if dev:
+ #set the type attribute of the device object
+ dev.setType(self.getType(cl.group(2)))
+ #get the vendorid
+ row = f.readline().replace("\n","")
+ if row:
+ vn = re.match('Vendor\:(.*)\[(.*)\]',row,re.I)
+ if vn:
+ dev.setVendorId(vn.group(2).replace("\t",""))
+ #get the productid
+ row = f.readline().replace("\n","")
+ if row:
+ pr = re.match('Device\:(.*)\[(.*)\]',row,re.I)
+ if pr:
+ dev.setProductId(pr.group(2).replace("\t",""))
+ dev.setModel(pr.group(1).replace("\t",""))
+
+ dev.setInterface('not-specified')
+ dev.setKernel(self.getKernel())
+
+ self.devices['p_' + dev.getVendorId() + ':' + dev.getProductId()] = [dev,cl.group(2),'insert','0']
+
+ else:
+ self._status = False
+ self.errors.append('the lspci -vmmnn output is not a standard output, some products row not found')
+ else:
+ self._status = False
+ self.errors.append('the lspci -vmmnn output is not a standard output, some vendors row not found')
+ else:
+ self._status = False
+ self.errors.append('the lspci -vmmnn output is not a standard output, some class row not found')
+
+ f.close();
+ else:
+ self._status = False
+ self.errors.append('tmp folder not writable')
+
+ #syncronize with the xml database
+ def sync(self):
+ #loop the found devices
+ for key,dev in self.devices.iteritems():
+ #find the class
+ Class = dev[1]
+ vendorid_productid = key[2:]
+ #find the controller
+ controller = self.getController(Class)
+
+ #perform an http request
+ self.request.contents = ''
+ self.request.perform('download/' + controller + '/en')
+
+ #parse the xml database
+ xmldoc = minidom.parseString(self.request.contents)
+ devices = xmldoc.getElementsByTagName("device")
+ for device in devices:
+
+ code = device.getElementsByTagName("vendorid_productid")[0]
+ if code.hasChildNodes():
+ if (code.childNodes[0].data == vendorid_productid):
+
+ modelName = device.getElementsByTagName("model_name")[0].childNodes[0].data
+ interface = device.getElementsByTagName("interface")[0].childNodes[0].data
+ distribution = device.getElementsByTagName("distribution")[0].childNodes[0].data
+ idDevice = device.getElementsByTagName("id")[0].childNodes[0].data
+ works = device.getElementsByTagName("it_works")[0].childNodes[0].data
+ year = device.getElementsByTagName("year")[0].childNodes[0].data
+ description = device.getElementsByTagName("description")[0].childNodes[0].data
+
+ #print modelName
+ dev[0].setModel(modelName)
+ dev[0].setInterface(interface)
+ dev[0].setDistributions(distribution)
+ dev[0].setHowItWorks(works)
+ dev[0].setYear(year)
+ dev[0].setDescription(description)
+ dev[2] = 'update'
+ dev[3] = idDevice
+
+ def submit(self):
+ for key,dev in self.devices.iteritems():
+ dev[0].setPost()
+ post = dev[0].getPost()
+ if dev[2] == 'update':
+ #get the node controller
+ controller = self.getController(dev[1])
+ #get the device id (inside the node database)
+ post['id_hard'] = dev[3]
+ post['updateAction'] = 'update'
+ #get the user info
+ info = self.getUserInfo()
+ token = info['token']
+ url = controller + '/update/en/' + token
+
+ self.request.setPost(post)
+ self.request.perform(url.encode('utf-8'))
+ #print self.request.contents
+
+
+#d = Videocard()
+
+#d.setVendor('Acer')
+#print d.getType()
+#d.setDistributions('trisquel_4_0,gnewsense');
+#print d.getStatus()
+
+client = Client('http://h-source/')
+client.createDevices()
+#client.request.perform('download/all/it')
+#print client.request.url
+client.sync()
+
+#for key,dev in client.devices.iteritems():
+ #print key
+ #print dev[0].getModel()
+ #print dev[0].getDistributions()
+ #print dev[0].getYear()
+ #print dev[3]
+ #print dev[0].getHowItWorks()
+ #print dev[0].getDescription()+"\n"+"\n"
+
+
+client.login('','')
+#print client.isLogged()
+client.submit()
+client.logout()
+#client.devices['p_14e4:4311'][0].setPost()
+#print client.devices['p_14e4:4311'][0].getPost() \ No newline at end of file