source: indico/indico/MaKaC/plugins/Collaboration/CERNMCU/collaboration.py @ 837615

burotelhello-world-walkthroughipv6new-webexprov-dual-interfacev0.97-seriesv0.98-seriesv0.98.2v0.98.3v0.98b1v0.98b2v0.99v1.0v1.1
Last change on this file since 837615 was 837615, checked in by David Martín Clavo <david.martin.clavo@…>, 4 years ago

[REFACTOR] Changes to CSErrorBase

-Changed getMessage method to getLogMessage and getUserMessage methods.
-getLogMessage should return a message to be written in the log.
-getUserMessage should return a message to be shown to the user,
for example when a synchronization between event and booking went bad.

  • Property mode set to 100644
File size: 35.3 KB
Line 
1# -*- coding: utf-8 -*-
2##
3## $Id: collaboration.py,v 1.6 2009/04/25 17:30:35 dmartinc Exp $
4##
5## This file is part of CDS Indico.
6## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 CERN.
7##
8## CDS Indico is free software; you can redistribute it and/or
9## modify it under the terms of the GNU General Public License as
10## published by the Free Software Foundation; either version 2 of the
11## License, or (at your option) any later version.
12##
13## CDS Indico is distributed in the hope that it will be useful, but
14## WITHOUT ANY WARRANTY; without even the implied warranty of
15## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16## General Public License for more details.
17##
18## You should have received a copy of the GNU General Public License
19## along with CDS Indico; if not, write to the Free Software Foundation, Inc.,
20## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
21
22from MaKaC.common.PickleJar import DictPickler
23from MaKaC.common.timezoneUtils import nowutc, setAdjustedDate
24from MaKaC.plugins.Collaboration.base import CSBookingBase
25from MaKaC.plugins.Collaboration.CERNMCU.common import CERNMCUException,\
26    ParticipantPerson, ParticipantRoom, getCERNMCUOptionValueByName,\
27    CERNMCUError, handleSocketError
28from MaKaC.common.utils import formatDateTime, validIP
29from MaKaC.plugins.Collaboration.CERNMCU.mcu import MCU, MCUConfCommonParams, MCUTime,\
30    paramsForLog, MCUParams, MCUParticipantCommonParams, datetimeFromMCUTime
31from MaKaC.i18n import _
32
33from xmlrpclib import Fault
34from datetime import timedelta
35from MaKaC.common.logger import Logger
36from MaKaC.common.Counter import Counter
37import socket
38
39class CSBooking(CSBookingBase):
40   
41    _hasTitle = True
42    _hasStart = True
43    _hasStop = True
44    _hasStartStopAll = True
45    _hasCheckStatus = True
46   
47    _requiresServerCallForStart = True
48    _requiresClientCallForStart = False
49   
50    _requiresServerCallForStop = True
51    _requiresClientCallForStop = False
52   
53    _needsBookingParamsCheck = True
54    _needsToBeNotifiedOnView = True
55   
56    _hasEventDisplay = True
57   
58    _commonIndexes = ["All Videoconference"]
59   
60    _complexParameters = ["pin", "hasPin", "autoGenerateId", "customId", "participants"]
61   
62    def __init__(self, type, conf):
63        CSBookingBase.__init__(self, type, conf)
64        self._bookingParams = {
65            "name": None,
66            "description": None,
67            "id": None
68        }
69       
70        self._oldName = None
71        self._pin = None
72        self._autoGeneratedId = None #boolean storing if the id was generated by Indico (True) or chosen by user (False)
73        self._customId = None #the custom id chosen by the user, if any
74        self._participants = {} #{id, Participant object}
75        self._participantIdCounter = Counter(1)
76       
77        self._created = False
78        self._creationTriesCounter = 0
79        self._hasBeenStarted = False
80       
81    def getMCUStartTime(self):
82        return MCUTime(self.getAdjustedStartDate('UTC') + timedelta(hours = getCERNMCUOptionValueByName("MCU_UTC_offset")))
83   
84    def getDurationSeconds(self):
85        diff = self.getEndDate() - self.getStartDate()
86        return diff.days * 86400 + diff.seconds
87   
88    def setAutoGenerateId(self, autoGenerateId):
89        self._autoGeneratedId = (autoGenerateId == 'yes')
90       
91    def getAutoGenerateId(self):
92        if self._autoGeneratedId:
93            return 'yes'
94        else:
95            return 'no'
96       
97    def setCustomId(self, customId):
98        self._customId = customId
99       
100    def getCustomId(self):
101        if self._autoGeneratedId:
102            return ''
103        else:
104            return self._customId
105
106    def getPin(self):
107        """ This method returns the pin that will be displayed in the indico page
108        """
109        return self._pin
110   
111    def setPin(self, accessPassword):
112        if accessPassword.strip() == "":
113            self._pin = ""
114        else:
115            self._pin = accessPassword
116           
117    def getHasPin(self):
118        return self._pin is not None and len(self._pin) > 0 
119   
120    def setHasPin(self, value):
121        #ignore, will be called only on rollback
122        pass
123       
124    def getParticipantList(self, sorted = False):
125        if sorted:
126            keys = self._participants.keys()
127            keys.sort()
128            return [self._participants[k] for k in keys]
129        else:
130            return self._participants.values()
131       
132    def getParticipants(self):
133        return DictPickler.pickle(self.getParticipantList(sorted = True))
134   
135    def setParticipants(self, participants):
136        participantsCopy = dict(self._participants)
137        self._participants = {}
138        for p in participants:
139            id = p.get("participantId", None)
140            if id is None or not id in participantsCopy:
141                id = self._participantIdCounter.newCount()
142           
143            if p["type"] == 'person':
144                participantObject = ParticipantPerson(self, id, p)
145            elif p["type"] == "room":
146                participantObject = ParticipantRoom(self, id, p)
147               
148            self._participants[id] = participantObject
149       
150        self._p_changed = 1
151
152   
153    ## overriding methods
154    def _getTitle(self):
155        return self._bookingParams["name"]
156   
157    def _getPluginDisplayName(self):
158        return "MCU"
159
160   
161    def _checkBookingParams(self):
162        if len(self._bookingParams["name"].strip()) == 0:
163            raise CERNMCUException("name parameter (" + str(self._bookingParams["name"]) +") is empty for booking with id: " + str(self._id))
164       
165        if len(self._bookingParams["name"]) >= 32:
166            raise CERNMCUException("name parameter (" + str(self._bookingParams["name"]) +") is longer than 31 characters for booking with id: " + str(self._id))
167       
168        self._bookingParams["name"] = self._bookingParams["name"].strip()
169
170        if len(self._bookingParams["description"].strip()) == 0:
171            raise CERNMCUException("description parameter (" + str(self._bookingParams["description"]) +") is empty for booking with id: " + str(self._id))
172       
173        if not self._autoGeneratedId:
174            if len(self._customId.strip()) == 0:
175                raise CERNMCUException("customId parameter (" + str(self._customId) +") is empty for booking with id: " + str(self._id))
176            else:
177                try:
178                    int(self._customId)
179                except ValueError:
180                    raise CERNMCUException("customId parameter (" + str(self._customId) +") is not an integer for booking with id: " + str(self._id))
181                if len(self._customId.strip()) != 5:
182                    raise CERNMCUException("customId parameter (" + str(self._customId) +") is longer than 5 digits for booking with id: " + str(self._id))
183                self._customId = int(self._customId)
184
185        if len(self._pin) >= 32:
186            raise CERNMCUException("pin parameter (" + str(self._pin) +") is longer than 31 characters for booking with id: " + str(self._id))
187       
188        #if self.getAdjustedStartDate('UTC')  < (nowutc()):
189        #    raise CERNMCUException("Cannot create booking in the past. Booking id: %s"% (str(self._id)))
190       
191        if self.getAdjustedEndDate('UTC')  < (nowutc()):
192            raise CERNMCUException("End date cannot be in the past. Booking id: %s"% (str(self._id)))
193       
194        minStartDate = self.getConference().getAdjustedStartDate()
195        if self.getAdjustedStartDate() < minStartDate:
196            raise CERNMCUException("Cannot create a booking before the Indico event's start date. Please create it after %s"%(formatDateTime(minStartDate)))
197
198        maxEndDate = self.getConference().getAdjustedEndDate()
199        if self.getAdjustedStartDate() > maxEndDate:
200            raise CERNMCUException("Cannot create a booking after before the Indico event's end date. Please create it after %s"%(formatDateTime(maxEndDate)))
201       
202        pSet = set()
203        ipSet = set()
204        for p in self._participants.itervalues():
205            if not validIP(p.getIp()):
206                raise CERNMCUException("Participant has not a correct ip. (ip string= " + p.getIp() + ")")
207           
208            if p.getType() == 'person':
209                if not p.getFamilyName():
210                    raise CERNMCUException("Participant (person) does not have family name.")
211                if not p.getFirstName():
212                    raise CERNMCUException("Participant (person) does not have first name.")
213            elif p.getType() == 'room':
214                if not p.getName():
215                    raise CERNMCUException("Participant (room) does not have name.")
216               
217            name = p.getParticipantName()
218            if name in pSet:
219                raise CERNMCUException("At least two of the participants will have the same name in the MCU. Please change their name, affiliation, ip, etc.")
220            else:
221                pSet.add(name)
222               
223            ip = p.getIp()
224            if ip in ipSet:
225                raise CERNMCUException("At least two of the participants have the same IP. Please change this")
226            else:
227                ipSet.add(ip)
228               
229        return False   
230   
231    def _create(self):
232        if self._autoGeneratedId:
233            if self._creationTriesCounter < 100:
234                id = self._plugin.getGlobalData().getNewConferenceId()
235            else:
236                return CERNMCUError('tooManyTries', "Could not obtain ID")
237        else:
238            id = self._customId
239           
240        try:
241            mcu = MCU.getInstance()
242            params = MCUConfCommonParams(conferenceName = self._bookingParams["name"],
243                                         numericId = str(id),
244                                         startTime = self.getMCUStartTime(),
245                                         durationSeconds = self.getDurationSeconds(),
246                                         pin = self._pin,
247                                         description = self._bookingParams["description"][:31],
248                                        )
249            Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling conference.create with params: %s""" % (self._conf.getId(), self.getId(), str(paramsForLog(params))))
250            answer = mcu.conference.create(params)
251            Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling conference.create. Got answer: %s""" % (self._conf.getId(), self.getId(), str(answer)))
252           
253            for p in self._participants.itervalues():
254                result = self.addParticipant(p)
255                if not result is True:
256                    return result
257           
258            self._statusMessage = "Booking created"
259            self._statusClass = "statusMessageOK"
260            self._bookingParams["id"] = id
261            self._oldName = self._bookingParams["name"]
262            self._created = True
263            self.checkCanStart()
264           
265        except Fault, e:
266            Logger.get('CERNMCU').warning("""Evt:%s, calling conference.create. Got error: %s""" % (self._conf.getId(), str(e)))
267            return self.handleFault('create', e)
268       
269        except socket.error, e:
270            handleSocketError(e)
271
272    def _modify(self):
273        """ Relays to the MCU the changes donde by the user to the Indico booking object.
274            For the participants, we retrieve a list of existing participants.
275            If a participant is both in the MCU and the Indico booking, it is not touched.
276            Thus, we only delete in the MCU those having been removed, and we only create only those who have been added.
277            In this way we avoid disconnection of already connected participants.
278        """
279       
280        if self._created:
281           
282            if self._autoGeneratedId:
283                id = self._bookingParams["id"]
284            else:
285                id = self._customId
286               
287            try:
288                mcu = MCU.getInstance()
289                params = MCUConfCommonParams(conferenceName = self._oldName,
290                                         newConferenceName = self._bookingParams["name"],
291                                         numericId = str(id),
292                                         startTime = self.getMCUStartTime(),
293                                         durationSeconds = self.getDurationSeconds(),
294                                         pin = self._pin,
295                                         description = self._bookingParams["description"],
296                                         )
297                Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling conference.modify with params: %s""" % (self._conf.getId(), self.getId(), str(paramsForLog(params))))
298                answer = mcu.conference.modify(params)
299                Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling conference.modify. Got answer: %s""" % (self._conf.getId(), self.getId(), str(answer)))
300                self._bookingParams["id"] = id
301                self._oldName = self._bookingParams["name"]
302               
303               
304                #we take care of the participants
305                remoteParticipants = self.queryParticipants()
306                existingInBoth = {} #key: participantName, value: a Participant object
307               
308                for p in self._participants.itervalues():
309                    name = p.getParticipantName()
310                    if not name in remoteParticipants:
311                        result = self.addParticipant(p)
312                        if not result is True:
313                            return result
314                    else:
315                        existingInBoth[name] = p
316                       
317                for participantName, localParticipant in existingInBoth.iteritems():
318                    remoteParticipant = remoteParticipants[participantName]
319                    if remoteParticipant["ip"] != localParticipant.getIp():
320                        self.removeParticipant(participantName)
321                        self.addParticipant(localParticipant)
322                    elif remoteParticipant["displayName"] != localParticipant.getDisplayName():
323                        self.modifyParticipantDisplayName(participantName, localParticipant.getDisplayName())
324                       
325                participantNamesToBeRemoved = set(remoteParticipants) - set(existingInBoth)
326                for name in participantNamesToBeRemoved:
327                    result = self.removeParticipant(name)
328                    if not result is True:
329                        return result
330               
331                self._created = True
332                self.checkCanStart()
333               
334               
335            except Fault, e:
336                Logger.get('CERNMCU').warning("""Evt:%s, booking:%s, calling conference.modify. Got error: %s""" % (self._conf.getId(), self.getId(), str(e)))
337                return self.handleFault('modify', e)
338           
339            except socket.error, e:
340                handleSocketError(e)
341       
342        else: #not yet created because of errors: try to recreate
343            self._create()
344         
345    def _start(self):
346        self._checkStatus()
347        if self._canBeStarted:
348            try:
349                mcu = MCU.getInstance()
350                for p in self.getParticipantList(sorted = True):
351                    params = MCUParams(conferenceName = self._bookingParams["name"],
352                                       participantName = p.getParticipantName())
353                    Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling participant.connect with params: %s""" % (self._conf.getId(), self.getId(), str(paramsForLog(params))))
354                    answer = mcu.participant.connect(params)
355                    Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling participant.connect. Got answer: %s""" % (self._conf.getId(), self.getId(), str(answer)))
356               
357                self._statusMessage = "Conference started!"
358                self._canBeStarted = False
359                self._canBeStopped = True
360                self._hasBeenStarted = True
361               
362            except Fault, e:
363                Logger.get('CERNMCU').warning("""Evt:%s, booking:%s, calling participant.connect. Got error: %s""" % (self._conf.getId(), self.getId(), str(e)))
364                return self.handleFault('start', e)
365               
366            except socket.error, e:
367                handleSocketError(e)
368        else:
369            raise CERNMCUException("Conference cannot start yet!")
370       
371    def _stop(self):
372        if self._canBeStopped:
373            try:
374                mcu = MCU.getInstance()
375                for p in self.getParticipantList(sorted = True):
376                    try:
377                        params = MCUParams(conferenceName = self._bookingParams["name"],
378                                           participantName = p.getParticipantName())
379                        Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling participant.disconnect with params: %s""" % (self._conf.getId(), self.getId(), str(paramsForLog(params))))
380                        answer = mcu.participant.disconnect(params)
381                        Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling participant.disconnect. Got answer: %s""" % (self._conf.getId(), self.getId(), str(answer)))
382                    except Fault, e:
383                        Logger.get('CERNMCU').warning("""Evt:%s, booking:%s, calling participant.disconnect. Got error: %s""" % (self._conf.getId(), self.getId(), str(e)))
384                        fault = self.handleFault('stop', e)
385                        if fault:
386                            return fault
387               
388                self._statusMessage = "Conference stopped"
389                self._statusClass = "statusMessageOther"
390                self._canBeStarted = True
391                self._canBeStopped = False
392                self._hasBeenStarted = False
393               
394            except Fault, e:
395                Logger.get('CERNMCU').warning("""Evt:%s, booking:%s, calling participant.disconnect. Got error: %s""" % (self._conf.getId(), self.getId(), str(e)))
396                return self.handleFault('stop', e)
397               
398            except socket.error, e:
399                handleSocketError(e)
400        else:
401            raise CERNMCUException("Conference cannot be stopped")
402         
403    def _notifyOnView(self):
404        self.checkCanStart()
405           
406    def _checkStatus(self):
407        if self._created:
408            self.queryConference()
409            self.checkCanStart()
410                                       
411    def _delete(self, oldName = None):
412        if self._created:
413            if oldName:
414                name = oldName
415            else:
416                name = self._bookingParams["name"]
417           
418            try:
419                mcu = MCU.getInstance()
420                params = MCUParams(conferenceName = name)
421                Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling conference.destroy with params: %s""" % (self._conf.getId(), self.getId(), str(paramsForLog(params))))
422                answer = mcu.conference.destroy(params)
423                Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling conference.destroy. Got answer: %s""" % (self._conf.getId(), self.getId(), str(answer)))
424               
425                if not oldName:
426                    self._created = False
427            except Fault, e:
428                Logger.get('CERNMCU').warning("""Evt:%s, booking:%s, calling conference.destroy. Got error: %s""" % (self._conf.getId(), self.getId(), str(e)))
429                if e.faultCode == 4: #conference didn't exist in the MCU, but we delete it from Indico anyway
430                    pass
431                else:
432                    return self.handleFault('delete', e)
433            except socket.error, e:
434                handleSocketError(e)
435        else:
436            self._error = False
437   
438    ## end of overrided methods
439       
440    def addParticipant(self, participant):
441        """ Adds a participant to the MCU conference represented by this booking.
442            participant: a Participant object
443            returns: True if successful, a CERNMCUError if there is a problem in some cases, raises an Exception in others
444        """
445        try:
446            mcu = MCU.getInstance()
447           
448            params = MCUParticipantCommonParams(conferenceName = self._bookingParams["name"],
449                                                participantName = participant.getParticipantName(),
450                                                displayNameOverrideValue = participant.getDisplayName(),
451                                                address = participant.getIp()
452                                                )
453            Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling participant.add with params: %s""" % (self._conf.getId(), self.getId(), str(paramsForLog(params))))
454            answer = mcu.participant.add(params)
455            Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling participant.add. Got answer: %s""" % (self._conf.getId(), self.getId(), str(answer)))
456           
457            if self._hasBeenStarted:
458                #we have to connect the new participant
459                params = MCUParams(conferenceName = self._bookingParams["name"],
460                                   participantName = participant.getParticipantName())
461                Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling participant.connect with params: %s""" % (self._conf.getId(), self.getId(), str(paramsForLog(params))))
462                answer = mcu.participant.connect(params)
463                Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling participant.connect. Got answer: %s""" % (self._conf.getId(), self.getId(), str(answer)))
464           
465            return True
466        except Fault, e:
467            Logger.get('CERNMCU').warning("""Evt:%s, calling participant.add. Got error: %s""" % (self._conf.getId(), str(e)))
468            fault = self.handleFault('add', e)
469            fault.setInfo(participant.getIp())
470            return fault
471       
472    def modifyParticipantDisplayName(self, participantName, displayName):
473        """ Modifies the display name of a participant
474            returns: True if successful, a CERNMCUError if there is a problem in some cases, raises an Exception in others
475        """
476        try:
477            mcu = MCU.getInstance()
478           
479            if self._hasBeenStarted:
480                state = 'activeState'
481            else:
482                state = 'configuredState'
483           
484            params = MCUParticipantCommonParams(conferenceName = self._bookingParams["name"],
485                                                participantName = participantName,
486                                                displayNameOverrideValue = displayName,
487                                                operationScope = state
488                                                )
489            Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling participant.modify with params: %s""" % (self._conf.getId(), self.getId(), str(paramsForLog(params))))
490            answer = mcu.participant.modify(params)
491            Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling participant.modify. Got answer: %s""" % (self._conf.getId(), self.getId(), str(answer)))
492           
493            return True
494        except Fault, e:
495            Logger.get('CERNMCU').warning("""Evt:%s, calling participant.modify. Got error: %s""" % (self._conf.getId(), str(e)))
496            fault = self.handleFault('modifyParticipant', e)
497            fault.setInfo(participantName)
498            return fault
499       
500    def removeParticipant(self, participantName):
501        """ Removes a participant to the MCU conference represented by this booking.
502            participant: a participant name like the one returned by Participant.getParticipantName
503            returns: True if successful, a CERNMCUError if there is a problem in some cases, raises an Exception in others
504        """
505        try:
506            mcu = MCU.getInstance()
507           
508            params = MCUParams(conferenceName = self._bookingParams["name"],
509                               participantName = participantName)
510            Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling participant.remove with params: %s""" % (self._conf.getId(), self.getId(), str(paramsForLog(params))))
511            answer = mcu.participant.remove(params)
512            Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling participant.remove. Got answer: %s""" % (self._conf.getId(), self.getId(), str(answer)))
513            return True
514        except Fault, e:
515            Logger.get('CERNMCU').warning("""Evt:%s, calling participant.remove. Got error: %s""" % (self._conf.getId(), str(e)))
516            return self.handleFault('remove', e)
517       
518    def checkCanStart(self, changeMessage = True):
519        if self._created:
520            now = nowutc()
521            if self.getStartDate() < now and self.getEndDate() > now and not self._hasBeenStarted:
522                self._canBeStarted = True
523                self._canBeStopped = False
524               
525                if changeMessage:
526                    self._statusMessage = "Ready to start!"
527                    self._statusClass = "statusMessageOK"
528            else:
529                self._canBeStarted = False
530                if now > self.getEndDate() and changeMessage:
531                    self._statusMessage = "Already took place"
532                    self._statusClass = "statusMessageOther"
533                    self._needsToBeNotifiedOfDateChanges = False
534                    self._canBeNotifiedOfEventDateChanges = False
535
536    def queryConference(self):
537        """ Queries the MCU for information about a conference with the same conferenceName as self._bookingParams["name"]
538            If found, the attributes of the Indico booking object are updated, included the participants.
539            If not found, an error message will appear and the conference will be marked as not created.
540        """
541        try:
542            mcu = MCU.getInstance()
543           
544            enumerateID = None
545            keepAsking = True
546            found = False
547           
548            while keepAsking and not found:
549                if enumerateID:
550                    params = MCUParams(enumerateID = enumerateID)
551                else:
552                    params = MCUParams()
553               
554                Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling conference.enumerate with params: %s""" % (self._conf.getId(), self.getId(), str(paramsForLog(params))))
555                answer = mcu.conference.enumerate(params)
556                Logger.get('CERNMCU').debug("""Evt:%s, booking:%s, calling conference.enumerate. Got answer: %s""" % (self._conf.getId(), self.getId(), str(answer)))
557               
558                for conference in answer.get("conferences", []):
559                    if conference.get("conferenceName", None) == self._bookingParams["name"]:
560                        found = True
561                       
562                        remoteDescription = conference.get("description", '')
563                        if len(remoteDescription) < 31 or not self._bookingParams["description"].startswith(remoteDescription):
564                            self._bookingParams["description"] = remoteDescription
565                        self._bookingParams["id"] = conference.get("numericId", '')
566                        if not self._autoGeneratedId:
567                            self._customId = self._bookingParams["id"]
568                        self._oldName = self._bookingParams["name"]
569                        self._pin = conference.get("pin", '')
570                       
571                        remoteParticipants = self.queryParticipants()
572                        for id, participant in self._participants.items(): 
573                            if participant.getParticipantName() not in remoteParticipants:
574                                del self._participants[id]
575                       
576                        for participant in self._participants.itervalues():
577                            del remoteParticipants[participant.getParticipantName()]
578                       
579                        for participantName, attributes in remoteParticipants.iteritems():
580                            try:
581                                possibleParticipantId, rest = participantName.split('b')[1:]
582                                possibleBookingId, possibleConfId = rest.split('c')
583                            except ValueError:
584                                possibleParticipantId = None
585                                possibleBookingId = None
586                                possibleConfId = None
587                       
588                            idIsNumeric = True
589                            try:
590                                int(possibleParticipantId)
591                            except ValueError:
592                                idIsNumeric = False
593                           
594                            if idIsNumeric and possibleBookingId == self._id and possibleConfId == self.getConference().getId():
595                                self._participants[id] = ParticipantRoom(self, possibleParticipantId,
596                                                                         {"name": attributes["displayName"],
597                                                                          "ip": attributes["ip"]}, True)
598                            else:
599                                self._participants[id] = ParticipantRoom(self, participantName,
600                                                                         {"name": attributes["displayName"],
601                                                                          "ip": attributes["ip"]}, False)
602                           
603                       
604                        startTime = conference.get("startTime", None)
605                        if startTime:
606                            adjustedDate = setAdjustedDate(datetimeFromMCUTime(startTime), tz = 'UTC')
607                            delta = timedelta(hours = getCERNMCUOptionValueByName("MCU_UTC_offset"))
608                            self.setStartDate(adjustedDate - delta)
609
610                        durationSeconds = conference.get("durationSeconds", None)
611                        if durationSeconds:
612                            self.setEndDate(self.getStartDate() + timedelta(seconds = durationSeconds))
613                        else:
614                            self.setEndDate(self.getStartDate())
615                       
616                        self._created = True
617                        break
618                   
619                enumerateID = answer.get("enumerateID", None)
620                keepAsking = enumerateID is not None
621                   
622            if not found:
623                self._created = False
624               
625            self._p_changed = 1
626               
627        except Fault, e:
628            Logger.get('CERNMCU').warning("""Evt:%s, booking:%s, calling participants.enumerate. Got error: %s""" % (self._conf.getId(), self.getId(), str(e)))
629            raise e
630        except socket.error, e:
631            handleSocketError(e)
632       
633    def queryParticipants(self):
634        """ Queries the MCU for the list of participants of this conference,
635            using participant.enumerate.
636            Returns a list of Participant objects
637        """
638        try:
639            mcu = MCU.getInstance()
640            participants = {} #key = participantName, value = {displayName, ip}
641           
642            enumerateID = None
643            keepAsking = True
644           
645            while keepAsking:
646                if enumerateID:
647                    params = MCUParams(enumerateID = enumerateID)
648                else:
649                    params = MCUParams()
650           
651                Logger.get('CERNMCU').info("""Evt:%s, booking:%s, calling participants.enumerate with params: %s""" % (self._conf.getId(), self.getId(), str(paramsForLog(params))))
652                answer = mcu.participant.enumerate(params)
653                Logger.get('CERNMCU').debug("""Evt:%s, booking:%s, calling participants.enumerate. Got answer: %s""" % (self._conf.getId(), self.getId(), str(answer)))
654
655                for participant in answer.get("participants", []):
656                    if participant.get("conferenceName", None) == self._bookingParams["name"]:
657                        name = participant.get("participantName", None)
658                        displayName = participant.get("displayName", None)
659                        ip = participant.get("address", None)
660                        if name:
661                            participants[name] = {"displayName": displayName, "ip": ip}
662               
663                enumerateID = answer.get("enumerateID", None)
664                keepAsking = enumerateID is not None
665                   
666            return participants
667               
668
669        except Fault, e:
670            Logger.get('CERNMCU').warning("""Evt:%s, booking:%s, calling participants.enumerate. Got error: %s""" % (self._conf.getId(), self.getId(), str(e)))
671            raise e
672        except socket.error, e:
673            handleSocketError(e)
674           
675    def handleFault(self, operation, e):
676        self._faultCode = e.faultCode
677        self._faultString = e.faultString
678       
679        if e.faultCode == 14: #authorization error
680            raise CERNMCUException(_("Authorization Error while Indico tried to connect to the MCU.\nPlease report to Indico support."), e)
681       
682        if operation == 'create' or operation == 'modify':
683            if e.faultCode == 2: #duplicated name
684                fault = CERNMCUError(e.faultCode)
685                return fault
686            if e.faultCode == 6: #too many conferences in MCU, no more can be created
687                fault = CERNMCUError(e.faultCode)
688                return fault
689            elif e.faultCode == 18:  #duplicated ID
690                if self._autoGeneratedId:
691                    self._creationTriesCounter = self._creationTriesCounter + 1
692                    return self._create()
693                else:
694                    fault = CERNMCUError(e.faultCode)
695                    return fault
696            else: #another error
697                raise CERNMCUException(_("Problem with the MCU while creating or modifying a conference"), e)
698       
699        elif operation == 'delete':
700            raise CERNMCUException(_("Problem with the MCU while removing a conference"), e)
701       
702        elif operation == 'add':
703            if e.faultCode == 3: #duplicate participant name
704                fault = CERNMCUError(e.faultCode)
705                return fault
706            if e.faultCode == 7: #too many participants in MCU, no more can be created
707                fault = CERNMCUError(e.faultCode)
708                return fault
709            else:
710                raise CERNMCUException(_("Problem with the MCU while adding a participant"), e)
711           
712        elif operation == 'modifyParticipant':
713            raise CERNMCUException(_("Problem with the MCU while modifying the name of a participant"), e)
714       
715        elif operation == 'remove':
716            raise CERNMCUException(_("Problem with the MCU while removing a participant"), e)
717       
718        elif operation == 'start':
719            raise CERNMCUException(_("Problem with the MCU while starting a conference"), e)
720       
721        elif operation == 'stop':
722            if e.faultCode == 201: #we tried to disconnect a participant that was not connected
723                return None
724            elif e.faultCode == 5: #we tried to disconnect a participant that didn't exist
725                return None
726            else:
727                raise CERNMCUException(_("Problem with the MCU while stopping a conference"), e)
Note: See TracBrowser for help on using the repository browser.