summaryrefslogtreecommitdiff
path: root/meetingtools/ac
diff options
context:
space:
mode:
authorLeif Johansson <leifj@sunet.se>2012-10-04 15:39:08 +0200
committerLeif Johansson <leifj@sunet.se>2012-10-04 15:39:08 +0200
commit2bdad0ae7a3a6e4ec5116becd39910388b679ed2 (patch)
tree5afdfba0a93c1af50d53bdc245d57cc4053e109a /meetingtools/ac
parent873e7823970352d591deee5f67f47c5436ee0e84 (diff)
restructure
Diffstat (limited to 'meetingtools/ac')
-rw-r--r--meetingtools/ac/__init__.py57
-rw-r--r--meetingtools/ac/api.py214
2 files changed, 271 insertions, 0 deletions
diff --git a/meetingtools/ac/__init__.py b/meetingtools/ac/__init__.py
new file mode 100644
index 0000000..2bbd25f
--- /dev/null
+++ b/meetingtools/ac/__init__.py
@@ -0,0 +1,57 @@
+from meetingtools.ac.api import ACPClient
+import time
+from meetingtools.apps.cluster.models import acc_for_user
+from django.core.cache import cache
+from Queue import Queue
+import logging
+from django.contrib.auth.models import User
+
+_pools = {}
+
+MAXCALLS = 10
+MAXIDLE = 10
+
+class ClientPool(object):
+
+ def __init__(self,acc,maxsize=0,increment=2):
+ self._q = Queue(maxsize)
+ self._acc = acc
+ self._increment = increment
+
+ def allocate(self):
+ now = time.time()
+ api = None
+ while not api:
+ if self._q.empty():
+ for i in range(1,self._increment):
+ logging.debug("adding instance %d" % i)
+ api = ACPClient(self._acc.api_url,self._acc.user,self._acc.password,cpool=self)
+ self._q.put_nowait(api)
+
+ api = self._q.get()
+ if api and (api.age > MAXCALLS or now - api.lastused > MAXIDLE):
+ api = None
+ return api
+
+# with ac_api_client(acc) as api
+# ...
+
+def ac_api_client(o):
+ acc = o
+ logging.debug("ac_api_client(%s)" % repr(o))
+ if hasattr(o,'user') and isinstance(getattr(o,'user'),User):
+ acc = acc_for_user(getattr(o,'user'))
+ elif hasattr(o,'acc'):
+ acc = getattr(o,'acc')
+
+ tag = 'ac_api_client_%d' % acc.id
+ pool = _pools.get(tag)
+ if pool is None:
+ pool = ClientPool(acc,maxsize=30)
+ _pools[tag] = pool
+
+ return pool.allocate()
+
+
+
+ \ No newline at end of file
diff --git a/meetingtools/ac/api.py b/meetingtools/ac/api.py
new file mode 100644
index 0000000..5fbcfbf
--- /dev/null
+++ b/meetingtools/ac/api.py
@@ -0,0 +1,214 @@
+'''
+Created on Jan 31, 2011
+
+@author: leifj
+'''
+from StringIO import StringIO
+
+import httplib2
+from urllib import quote_plus
+import logging
+from pprint import pformat
+import os
+import tempfile
+import time
+from lxml import etree
+from meetingtools.site_logging import logger
+import lxml
+from django.http import HttpResponseRedirect
+from celery.execute import send_task
+
+class ACPException(Exception):
+ def __init__(self, value):
+ self.value = value
+
+ def __str__(self):
+ return etree.tostring(self.value)
+
+def _first_or_none(x):
+ if not x:
+ return None
+ return x[0]
+
+class ACPResult():
+
+ def __init__(self,content):
+ self.et = etree.fromstring(content)
+ self.status = _first_or_none(self.et.xpath('//status'))
+
+ def is_error(self):
+ return self.status_code() != 'ok'
+
+ def status_code(self):
+ return self.status.get('code')
+
+ def subcode(self):
+ return self.status.get('subcode')
+
+ def exception(self):
+ raise ACPException,self.status
+
+ def get_principal(self):
+ logger.debug(lxml.etree.tostring(self.et))
+ return _first_or_none(self.et.xpath('//principal'))
+
+def _enc(v):
+ ev = v
+ if isinstance(ev,str) or isinstance(ev,unicode):
+ ev = ev.encode('iso-8859-1')
+ return ev
+
+def _getset(d,key,value=None):
+ if value:
+ if d.has_key(key):
+ return d[key]
+ else:
+ return None
+ else:
+ d[key] = value
+
+class ACPClient():
+
+ def __init__(self,url,username=None,password=None,cache=True,cpool=None):
+ self._cpool = cpool
+ self.age = 0
+ self.createtime = time.time()
+ self.lastused = self.createtime
+ self.url = url
+ self.session = None
+ if username and password:
+ self.login(username,password)
+ if cache:
+ self._cache = {'login':{},'group':{}}
+
+ def __exit__(self,type,value,traceback):
+ if self._cpool and not value:
+ self._cpool._q.put_nowait(self)
+
+ def __enter__(self):
+ return self
+
+
+ def request(self,method,p={},raise_error=False):
+ self.age += 1
+ self.lastused = time.time()
+ u = list()
+ u.append("action=%s" % method)
+ if self.session:
+ u.append("session=%s" % self.session)
+ for k,v in p.items():
+ value = v
+ if type(v) == int:
+ value = "%d" % value
+ u.append('%s=%s' % (k,quote_plus(value.encode("utf-8"))))
+
+ url = self.url + '?' + '&'.join(u)
+
+ h = httplib2.Http(tempfile.gettempdir()+os.sep+".cache",disable_ssl_certificate_validation=True);
+ logging.debug(url)
+ resp, content = h.request(url, "GET")
+ logging.debug(pformat(resp))
+ logging.debug(pformat(content))
+ if resp.status != 200:
+ raise ACPException,resp.reason
+
+ if resp.has_key('set-cookie'):
+ cookie = resp['set-cookie']
+ if cookie:
+ avp = cookie.split(";")
+ if len(avp) > 0:
+ av = avp[0].split('=')
+ self.session = av[1]
+
+ r = ACPResult(content)
+ if r.is_error() and raise_error:
+ raise r.exception()
+
+ return r;
+
+ def redirect_to(self,url):
+ if self.session:
+ return HttpResponseRedirect("%s?session=%s" % (url,self.session))
+ else:
+ return HttpResponseRedirect(url)
+
+ def login(self,username,password):
+ result = self.request('login',{'login':username,'password':password})
+ if result.is_error():
+ raise result.exception()
+ return result
+
+ def find_or_create_principal(self,key,value,t,d):
+ if not self._cache.has_key(t):
+ self._cache[t] = {}
+ cache = self._cache[t]
+
+ # lxml etree Elements are not picklable
+ p = None
+ if not cache.has_key(key):
+ p = self._find_or_create_principal(key,value,t,d)
+ cache[key] = etree.tostring(p)
+ else:
+ p = etree.parse(StringIO(cache[key]))
+ return p
+
+ def find_principal(self,key,value,t):
+ return self.find_or_create_principal(key,value,t,None)
+
+ def _find_or_create_principal(self,key,value,t,d):
+ result = self.request('principal-list',{'filter-%s' % key: value,'filter-type': t}, True)
+ principal = result.get_principal()
+ if result.is_error():
+ if result.status_code() != 'no_data':
+ result.exception()
+ elif principal and d:
+ d['principal-id'] = principal.get('principal-id')
+
+ rp = principal
+ if d:
+ update_result = self.request('principal-update',d)
+ rp = update_result.get_principal()
+ if not rp:
+ rp = principal
+ return rp
+
+ def find_builtin(self,t):
+ result = self.request('principal-list', {'filter-type': t}, True)
+ return result.get_principal()
+
+ def find_group(self,name):
+ result = self.request('principal-list',{'filter-name':name,'filter-type':'group'},True)
+ return result.get_principal()
+
+ def find_user(self,login):
+ return self.find_principal("login", login, "user")
+
+ def add_remove_member(self,principal_id,group_id,is_member):
+ m = "0"
+ if is_member:
+ m = "1"
+ self.request('group-membership-update',{'group-id': group_id, 'principal-id': principal_id,'is-member':m},True)
+
+ def add_member(self,principal_id,group_id):
+ return self.add_remove_member(principal_id, group_id, True)
+
+ def remove_member(self,principal_id,group_id):
+ return self.add_remove_member(principal_id, group_id, False)
+
+ def user_counts(self,sco_id):
+ user_count = None
+ host_count = None
+ userlist = self.request('meeting-usermanager-user-list',{'sco-id': sco_id},False)
+ if userlist.status_code() == 'ok':
+ user_count = int(userlist.et.xpath("count(.//userdetails)"))
+ host_count = int(userlist.et.xpath("count(.//userdetails/role[text() = 'host'])"))
+ elif userlist.status_code() == 'no-access' and userlist.subcode() == 'not-available': #no active session
+ user_count = 0
+ host_count = 0
+
+ return (user_count,host_count)
+
+ def poll_user_counts(self,room):
+ (room.user_count,room.host_count) = self.user_counts(room.sco_id)
+ room.save()
+ return (room.user_count,room.host_count) \ No newline at end of file