PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/indico/MaKaC/plugins/Collaboration/CERNMCU/common.py

https://github.com/flannery/indico-flannery
Python | 351 lines | 311 code | 21 blank | 19 comment | 14 complexity | b445e87d69629127f29773365e521903 MD5 | raw file
  1. # -*- coding: utf-8 -*-
  2. ##
  3. ##
  4. ## This file is part of CDS Indico.
  5. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 CERN.
  6. ##
  7. ## CDS Indico is free software; you can redistribute it and/or
  8. ## modify it under the terms of the GNU General Public License as
  9. ## published by the Free Software Foundation; either version 2 of the
  10. ## License, or (at your option) any later version.
  11. ##
  12. ## CDS Indico is distributed in the hope that it will be useful, but
  13. ## WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. ## General Public License for more details.
  16. ##
  17. ## You should have received a copy of the GNU General Public License
  18. ## along with CDS Indico; if not, write to the Free Software Foundation, Inc.,
  19. ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  20. from persistent import Persistent
  21. from MaKaC.plugins.Collaboration.base import CollaborationException, CSErrorBase
  22. from MaKaC.plugins.base import PluginsHolder
  23. from random import Random
  24. from MaKaC.common.PickleJar import Retrieves
  25. from MaKaC.plugins.Collaboration.collaborationTools import CollaborationTools
  26. from datetime import timedelta
  27. import socket
  28. import errno
  29. from MaKaC.common.fossilize import fossilizes, Fossilizable
  30. from MaKaC.plugins.Collaboration.CERNMCU.fossils import IRoomWithH323Fossil, ICERNMCUErrorFossil
  31. from MaKaC.plugins.Collaboration.CERNMCU.fossils import IParticipantPersonFossil,\
  32. IParticipantRoomFossil, IRoomWithH323Fossil, ICERNMCUErrorFossil
  33. secondsToWait = 10
  34. def getCERNMCUOptionValueByName(optionName):
  35. return CollaborationTools.getOptionValue('CERNMCU', optionName)
  36. def getMinMaxId():
  37. idRangeString = getCERNMCUOptionValueByName("idRange")
  38. return tuple([int(s) for s in idRangeString.split('-')])
  39. def getRangeLength():
  40. idRangeString = getCERNMCUOptionValueByName("idRange")
  41. minimum, maximum = [int(s) for s in idRangeString.split('-')]
  42. return maximum - minimum
  43. def getMinStartDate(conference):
  44. return conference.getAdjustedStartDate() - timedelta(0,0,0,0, getCERNMCUOptionValueByName("extraMinutesBefore"))
  45. def getMaxEndDate(conference):
  46. return conference.getAdjustedEndDate() + timedelta(0,0,0,0, getCERNMCUOptionValueByName("extraMinutesAfter"))
  47. def getGlobalData():
  48. return PluginsHolder().getPluginType('Collaboration').getPlugin('CERNMCU').getGlobalData()
  49. class GlobalData(Persistent):
  50. def __init__(self):
  51. self._usedIds = set()
  52. self._randomGenerator = Random()
  53. self._min = None
  54. self._max = None
  55. self._idList = None
  56. self._counter = 0
  57. def getNewConferenceId(self):
  58. if self._idList is None:
  59. self._min, self._max = getMinMaxId()
  60. self._idList = range(self._min, self._max + 1)
  61. self._randomGenerator.shuffle(self._idList)
  62. self._counter = 0
  63. if len(self._usedIds) > self._max - self._min + 1:
  64. raise CERNMCUException("No more Conference ids available for the MCU")
  65. while True:
  66. mcuConferenceId = self._idList[self._counter % len(self._idList)]
  67. self._counter = self._counter + 1
  68. if not mcuConferenceId in self._usedIds:
  69. break
  70. return mcuConferenceId
  71. def getMinMax(self):
  72. return self._min, self._max
  73. def resetIdList(self):
  74. self._idList = None
  75. def addConferenceId(self, mcuConferenceId):
  76. self._usedIds.add(mcuConferenceId)
  77. def removeConferenceId(self, mcuConferenceId):
  78. self._usedIds.remove(mcuConferenceId)
  79. class Participant(Persistent):
  80. def __init__(self, personOrRoom, booking, participantIndicoId, ip,
  81. participantName = None, participantType = "by_address", participantProtocol = "h323",
  82. createdByIndico = True):
  83. """ personOrRoom: a string which can be "person" or "room"
  84. booking: the CSBooking object parent of this participant
  85. participantIndicoId: an auto-increment integer, indexing the participants of the same booking, no matter their nature
  86. participantName: if left to None, we will generate it, example: i-c10b2p4
  87. otherwise, we pick whatever comes as argument (useful for ad-hoc participants)
  88. participantType: the participantType attribute of this participant in the MCU (can be by_address for Indico created
  89. participants, ad_hoc for ad_hoc ones, by_name for permanent ones pre-configured in the MCU)
  90. participantProtocol: the participantProtocol attribute of the participant in the MCU
  91. createdByIndico: a boolean stating if the participant was created by Indico or was created by someone else in the MCU.
  92. """
  93. self._type = personOrRoom
  94. self._booking = booking
  95. self._id = participantIndicoId
  96. self._ip = ip
  97. self._participantName = participantName
  98. self._participantType = participantType
  99. self._participantProtocol = participantProtocol
  100. self._createdByIndico = createdByIndico
  101. self._callState = "dormant" #dormant: at creation, before start. others: connected (after start), disconnected (after stop or ad hoc when leaves)
  102. def updateData(self, newData):
  103. """ To be overloaded by inheriting classes
  104. """
  105. pass
  106. def isCreatedByIndico(self):
  107. """
  108. Who created it? Indico or MCU, remotely?
  109. """
  110. return self._createdByIndico
  111. def getType(self):
  112. return self._type
  113. def getId(self):
  114. return self._id
  115. def getParticipantName(self):
  116. """ During booking creation, this method should not be called before
  117. the booking object has an id (see CSBookingManager.createBooking method).
  118. """
  119. if not hasattr(self, "_participantName") or self._participantName is None:
  120. self._participantName = self._createParticipantName()
  121. return self._participantName
  122. def getDisplayName(self):
  123. """ To be overloaded by inheriting classes
  124. """
  125. pass
  126. def getIp(self):
  127. return self._ip
  128. def setIp(self, ip):
  129. self._ip = ip
  130. def getParticipantType(self):
  131. if not hasattr(self, "_participantType"):
  132. self._participantType = "by_address"
  133. return self._participantType
  134. def setParticipantType(self, participantType):
  135. self._participantType = participantType
  136. def getParticipantProtocol(self):
  137. if not hasattr(self, "_participantProtocol"):
  138. self._participantProtocol = "h323"
  139. return self._participantProtocol
  140. def setParticipantProtocol(self, participantProtocol):
  141. self._participantProtocol = participantProtocol
  142. def getCallState(self):
  143. if not hasattr(self, "_callState"):
  144. self._callState = "dormant"
  145. return self._callState
  146. def setCallState(self, callState):
  147. self._callState = callState
  148. def _createParticipantName(self):
  149. confId = self._booking.getConference().getId()
  150. bookingId = self._booking.getId()
  151. participantName = "i-c%sb%sp%s" % (confId, bookingId, self._id)
  152. if len(participantName) > 31:
  153. raise CERNMCUException("Generated participantName is longer than 31 characters. Conf %s, booking %s, participant %s (%s)" %
  154. (confId, bookingId, self._id, self.getDisplayName()))
  155. return participantName
  156. class ParticipantPerson(Participant, Fossilizable):
  157. fossilizes(IParticipantPersonFossil)
  158. def __init__(self, booking, participantIndicoId, data):
  159. self._title = data.get("title", '')
  160. self._familyName = data.get("familyName", '')
  161. self._firstName = data.get("firstName", '')
  162. self._affiliation = data.get("affiliation", '')
  163. Participant.__init__(self, 'person', booking, participantIndicoId, data.get("ip",''),
  164. participantName = None, participantType = "by_address", participantProtocol = data.get("participantProtocol", "h323"),
  165. createdByIndico = True)
  166. def updateData(self, newData):
  167. self._title = newData.get("title", '')
  168. self._familyName = newData.get("familyName", '')
  169. self._firstName = newData.get("firstName", '')
  170. self._affiliation = newData.get("affiliation", '')
  171. self._participantProtocol = newData.get("participantProtocol", '')
  172. self.setIp(newData.get("ip", ''))
  173. def getTitle(self):
  174. return self._title
  175. def getFamilyName(self):
  176. return self._familyName
  177. def getFirstName(self):
  178. return self._firstName
  179. def getAffiliation(self):
  180. return self._affiliation
  181. def getDisplayName(self, truncate=True):
  182. result = []
  183. if self._title:
  184. result.append(self._title)
  185. result.append(' ')
  186. result.append(self._familyName.upper())
  187. result.append(', ')
  188. result.append(self._firstName)
  189. if self._affiliation:
  190. result.append(' (')
  191. result.append(self._affiliation)
  192. result.append(')')
  193. result = "".join(result)
  194. if truncate:
  195. return result[:31] #31 is the max length accepted by the MCU
  196. else:
  197. return result
  198. class ParticipantRoom(Participant, Fossilizable):
  199. fossilizes(IParticipantRoomFossil)
  200. def __init__(self, booking, participantIndicoId, data,
  201. participantName = None, participantType = "by_address",
  202. createdByIndico = True):
  203. self._name = data.get("name",'')
  204. self._institution = data.get("institution", '')
  205. Participant.__init__(self, 'room', booking, participantIndicoId, data.get("ip",''),
  206. participantName, participantType, data.get("participantProtocol", "h323"),
  207. createdByIndico)
  208. def updateData(self, newData):
  209. self._name = newData.get("name",'')
  210. self._institution = newData.get("institution", '')
  211. self._participantProtocol = newData.get("participantProtocol", '')
  212. self.setIp(newData.get("ip", ''))
  213. def getName(self):
  214. return self._name
  215. def setName(self, name):
  216. self._name = name
  217. def getInstitution(self):
  218. if not hasattr(self, '_institution'):
  219. self._institution = ''
  220. return self._institution
  221. def setInstitution(self, institution):
  222. self._institution = institution
  223. def getDisplayName(self, truncate=True):
  224. result = self._name
  225. if self._institution:
  226. result = result + ' (' + self._institution + ')'
  227. if truncate:
  228. return result[:31] #31 is the max length accepted by the MCU
  229. else:
  230. return result
  231. class RoomWithH323(Fossilizable):
  232. fossilizes(IRoomWithH323Fossil)
  233. def __init__(self, institution, name, ip):
  234. self._institution = institution
  235. self._name = name
  236. self._ip = ip
  237. def getLocation(self):
  238. return self._institution
  239. def getName(self):
  240. return self._name
  241. def getIp(self):
  242. return self._ip
  243. class CERNMCUError(CSErrorBase): #already fossilizable
  244. fossilizes(ICERNMCUErrorFossil)
  245. def __init__(self, faultCode, info = ''):
  246. self._faultCode = faultCode
  247. self._info = info
  248. def getFaultCode(self):
  249. return self._faultCode
  250. def getInfo(self):
  251. return self._info
  252. def setInfo(self, info):
  253. self._info = info
  254. def getUserMessage(self):
  255. return ''
  256. def getLogMessage(self):
  257. message = "CERNMCU Error. Fault code: " + str(self._faultCode)
  258. if self._info:
  259. message += ". Info: " + str(self._info)
  260. return message
  261. class CERNMCUException(CollaborationException):
  262. def __init__(self, msg, inner = None):
  263. CollaborationException.__init__(self, msg, 'CERN MCU', inner)
  264. def handleSocketError(e):
  265. if e.args[0] == errno.ETIMEDOUT:
  266. raise CERNMCUException("CERN's MCU may be offline. Indico encountered a network problem while connecting with the MCU at " + getCERNMCUOptionValueByName('MCUAddress') + ". Connection with the MCU timed out after %s seconds"%secondsToWait)
  267. elif e.args[0] == errno.ECONNREFUSED:
  268. raise CERNMCUException("CERN's MCU seems to have problems. Network problem while connecting with the MCU at " + getCERNMCUOptionValueByName('MCUAddress') + ". The connection with the MCU was refused.")
  269. elif isinstance(e, socket.gaierror) and e.args[0] == socket.EAI_NODATA:
  270. raise CERNMCUException("Network problem while connecting with the MCU at " + getCERNMCUOptionValueByName('MCUAddress') + ". Indico could not resolve the IP address for that host name.")
  271. else:
  272. raise CERNMCUException("Network problem while connecting with the MCU at " + getCERNMCUOptionValueByName('MCUAddress') + ". Problem: " + str(e))