def disconnectRoom(cls, booking, connectionStatus, roomIp="", roomPanoramaUser=""): serviceType = connectionStatus.get("service") # roomName should be empty if we are forcing disconnection (otherwise we'd be sending the wrong name and # disconnetion would fail) if connectionStatus.get("roomName") == booking.getBookingParamByName( "roomName"): roomName = booking.getBookingParamByName("roomName") else: roomName = "" try: if roomIp != "": answer = RavemApi.disconnectLegacyEndpoint( roomIp, serviceType, roomName) else: answer = RavemApi.disconnectVidyoPanorama( roomPanoramaUser, serviceType, roomName) if not answer.ok or "error" in answer.json(): Logger.get('Vidyo').exception("""Evt:%s, booking:%s, Ravem API's disconnect operation not successfull: %s""" % (booking.getConference().getId(), booking.getId(), answer.text)) return VidyoError( "disconnectFailed", "disconnect", _("Vidyo was unable to disconnect the conference room. {0}" ).format(VidyoTools.getContactSupportText())) except Exception: return VidyoError( "disconnectFailed", "disconnect", _("Vidyo was unable to disconnect the conference room. {0}"). format(VidyoTools.getContactSupportText()))
def _checkBookingParams(self): if len(self._bookingParams["roomName"].strip()) == 0: raise VidyoException("roomName parameter (" + str(self._bookingParams["roomName"]) + " ) is empty for Vidyo booking with id: " + str(self._id)) elif unicodeLength(self._bookingParams["roomName"] ) > VidyoTools.maxRoomNameLength( self.getOriginalConferenceId()): return VidyoError("nameTooLong") else: if not VidyoTools.verifyRoomName(self._bookingParams["roomName"]): return VidyoError("invalidName") else: self._bookingParams[ "roomName"] = VidyoTools.replaceSpacesInName( self._bookingParams["roomName"]) if len(self._bookingParams["roomDescription"].strip()) == 0: raise VidyoException("roomDescription parameter (" + str(self._bookingParams["roomDescription"]) + " ) is empty for Vidyo booking with id: " + str(self._id)) if self._pin and not self._pin.isdigit(): raise VidyoException( "pin parameter ({0}) is not an integer for Vidyo booking with id: {1}" .format(self._pin, self._id)) if self._moderatorPin and not self._moderatorPin.isdigit(): raise VidyoException( "moderator pin parameter ({0}) is not an integer for Vidyo booking with id: {1}" .format(self._moderatorPin, self._id)) return False
def connectRoom(cls, booking, roomId, query): confId = booking.getConference().getId() bookingId = booking.getId() try: searchFilter = SOAPObjectFactory.createFilter('user', query) userApiAnswer = UserApi.search(searchFilter) if userApiAnswer.total == 0: return VidyoError( "noExistsRoom", "connect", _("The conference room is not registered in the vidyo service. " ) + VidyoTools.getContactSupportText()) legacyMember = userApiAnswer.Entity[0].entityID AdminApi.connectRoom(roomId, legacyMember) except WebFault, e: faultString = e.fault.faultstring if faultString.startswith('ConferenceID is invalid'): return VidyoError("unknownRoom", "connect") elif (faultString.startswith('Failed to Invite to Conference') or faultString.startswith( 'Status of invited member is not Online')): message = _("The connection has failed. " ) + VidyoTools.getContactSupportText() return VidyoError("connectFailed", "connect", message) else: Logger.get('Vidyo').exception( """Evt:%s, booking:%s, Admin API's connectRoom operation got WebFault: %s""" % (confId, bookingId, e.fault.faultstring)) raise
def isRoomConnected(cls, booking, roomIp): try: answer = RavemApi.isRoomConnected(roomIp) if not answer.ok or answer.json.has_key("error"): Logger.get('Vidyo').exception( """Evt:%s, booking:%s, Ravem API's isRoomConnected operation not successfull: %s""" % (booking.getConference().getId(), booking.getId(), answer.text)) return VidyoError( "roomCheckFailed", "roomConnected", _("There was a problem obtaining the room status. ") + VidyoTools.getContactSupportText()) result = {"roomName": None, "isConnected": False, "service": None} answer = answer.json if answer.has_key("result"): for service in answer.get("result").get("services"): if service.get("name", "") == "videoconference": result["roomName"] = VidyoTools.recoverVidyoName( service.get("eventName")) result["isConnected"] = service.get("status") == 1 result["service"] = VidyoTools.recoverVidyoDescription( service.get("eventType")) return result except Exception: return VidyoError( "roomCheckFailed", "roomConnected", _("There was a problem obtaining the room status. ") + VidyoTools.getContactSupportText())
def isRoomConnected(cls, booking, roomIp="", roomPanoramaUser=""): try: if roomIp != "": answer = RavemApi.isLegacyEndpointConnected(roomIp) else: answer = RavemApi.isVidyoPanoramaConnected(roomPanoramaUser) if not answer.ok or "error" in answer.json(): Logger.get('Vidyo').exception("""Evt:%s, booking:%s, Ravem API's isConnected operation not successfull: %s""" % (booking.getConference().getId(), booking.getId(), answer.text)) return VidyoError( "roomCheckFailed", "roomConnected", _("There was a problem obtaining the room status from Vidyo. {0}" ).format(VidyoTools.getContactSupportText())) result = {"roomName": None, "isConnected": False, "service": None} answer = answer.json() if "result" in answer: for service in answer.get("result").get("services"): if service.get("name", "") == "videoconference": result["roomName"] = VidyoTools.recoverVidyoName( service.get("event_name")) result["isConnected"] = service.get("status") == 1 result["service"] = VidyoTools.recoverVidyoDescription( service.get("event_type")) return result except Exception: return VidyoError( "roomCheckFailed", "roomConnected", _("There was a problem obtaining the room status from Vidyo. {0}" ).format(VidyoTools.getContactSupportText()))
def _connect(self, force=False): self._checkStatus() connectionStatus = self.connectionStatus() if isinstance(connectionStatus, VidyoError): return connectionStatus confRoomIp = VidyoTools.getLinkRoomIp(self.getLinkObject()) if confRoomIp == "": return VidyoError("noValidConferenceRoom", "connect") if connectionStatus.get("isConnected") == True: if connectionStatus.get("roomName") == self.getBookingParamByName( "roomName"): return VidyoError( "alreadyConnected", "connect", _("It seems that the room has been already connected to the room, please refresh the page." )) if not force: # if connect is not forced, give up return VidyoError( "alreadyConnected", "connect", _("The room is already connected to some other endpoint. Please refresh the page." )) else: # otherwise, replace whatever call is going on ExternalOperationsManager.execute( self, "disconnectRoom", VidyoOperations.disconnectRoom, self, confRoomIp, connectionStatus.get("service")) retry = 15 connected = True # wait for the current call to be disconnected while retry: connectionStatus = self.connectionStatus() time.sleep(2) retry -= 1 if connectionStatus.get("isConnected") == False: connected = False break if connected: return VidyoError( "couldntStop", "connect", _("It seems like we haven't managed to stop " "the current call. Please refresh the page and try again." )) else: # give it some time before trying to connect time.sleep(5) prefixConnect = getVidyoOptionValue("prefixConnect") result = ExternalOperationsManager.execute(self, "connectRoom", VidyoOperations.connectRoom, self, self._roomId, prefixConnect + confRoomIp) if isinstance(result, VidyoError): return result return self
def disconnectRoom(cls, booking, roomIp, serviceType): try: answer = RavemApi.disconnectRoom(roomIp, serviceType) if not answer.ok or answer.json.has_key("error"): Logger.get('Vidyo').exception( """Evt:%s, booking:%s, Ravem API's disconnectRoom operation not successfull: %s""" % (booking.getConference().getId(), booking.getId(), answer.text)) return VidyoError( "disconnectFailed", "disconnect", _("There was a problem with the videoconference disconnection. " ) + VidyoTools.getContactSupportText()) except Exception: return VidyoError( "disconnectFailed", "disconnect", _("There was a problem with the videoconference disconnection. " ) + VidyoTools.getContactSupportText())
def checkAttachParams(self, bookingParams): if bookingParams["roomName"] == self.getBookingParamByName("roomName") and \ bookingParams.get("videoLinkType") == self.getBookingParamByName("videoLinkType") and \ (bookingParams.get("videoLinkType") == "event" or (bookingParams.get("videoLinkType") == "session" and bookingParams.get("videoLinkSession") == self.getBookingParamByName("videoLinkSession")) or (bookingParams.get("videoLinkType") == "contribution" and bookingParams.get("videoLinkContribution") == self.getBookingParamByName("videoLinkContribution"))): return VidyoError("duplicated", "attach")
def _disconnect(self): self._checkStatus() confRoomIp = VidyoTools.getLinkRoomIp(self.getLinkObject()) if confRoomIp == "": return VidyoError("noValidConferenceRoom", "disconnect") connectionStatus = self.connectionStatus() if isinstance(connectionStatus, VidyoError): return connectionStatus if not connectionStatus.get("isConnected"): return VidyoError( "alreadyDisconnected", "disconnect", _("It seems that the room has been already disconnected, please refresh the page" )) result = ExternalOperationsManager.execute( self, "disconnectRoom", VidyoOperations.disconnectRoom, self, confRoomIp, connectionStatus.get("service")) if isinstance(result, VidyoError): return result return self
def attachRoom(cls, booking): owner = booking.getOwnerObject() possibleLogins = VidyoTools.getAvatarLoginList(owner) if not possibleLogins: return VidyoError("userHasNoAccounts", "attach") roomName = booking.getBookingParamByName("roomName") searchFilter = SOAPObjectFactory.createFilter('admin', roomName) # TODO: Do several calls if needed # Vidyo should have an exact match feature too searchFilter.limit = 100 answer = AdminApi.getRooms(searchFilter) createdRooms = answer.room for room in createdRooms: for login in possibleLogins: if str(room.name) == roomName and str(room.ownerName) == login: return room else: return VidyoError("notValidRoom", "attach")
def deleteRoom(cls, booking, roomId): confId = booking.getConference().getId() bookingId = booking.getId() try: AdminApi.deleteRoom(roomId) except WebFault, e: faultString = e.fault.faultstring if faultString.startswith('Room not found for roomID'): return VidyoError("unknownRoom", "delete") else: Logger.get('Vidyo').exception( """Evt:%s, booking:%s, Admin API's deleteRoom operation got WebFault: %s""" % (confId, bookingId, e.fault.faultstring)) raise
def getAutomute(cls, booking): confId = booking.getConference().getId() bookingId = booking.getId() roomId = booking.getRoomId() try: return AdminApi.getAutomute(roomId) except WebFault, e: faultString = e.fault.faultstring if faultString.startswith('Room not found for roomID'): return VidyoError("unknownRoom", "getAutomute") else: Logger.get('Vidyo').exception( """Evt:%s, booking:%s, Admin API's getAutomute operation got WebFault: %s""" % (confId, bookingId, e.fault.faultstring))
def setModeratorPIN(cls, booking): confId = booking.getConference().getId() bookingId = booking.getId() roomId = booking.getRoomId() moderatorPIN = booking.getModeratorPin() try: AdminApi.setModeratorPIN(roomId, moderatorPIN) except WebFault, e: faultString = e.fault.faultstring if faultString.startswith('Room not found for roomID'): return VidyoError("unknownRoom", "setModeratorPIN") else: Logger.get('Vidyo').exception( """Evt:%s, booking:%s, Admin API's setModeratorPIN operation got WebFault: %s""" % (confId, bookingId, e.fault.faultstring))
def queryRoom(cls, booking, roomId): """ Searches for room information via the admin api's getRoom function and the user api's search function (currently the admin api's getRoom is not reliable to retrieve name, description and groupName). Tries to find the room providing the extension as query (since only the room name and extension are checked by the search op). Returns None if not found """ confId = booking.getConference().getId() bookingId = booking.getId() roomId = booking.getRoomId() try: adminApiRoom = AdminApi.getRoom(roomId) except WebFault, e: faultString = e.fault.faultstring if faultString.startswith('Room not found for roomID'): return VidyoError("unknownRoom", "checkStatus") else: Logger.get('Vidyo').exception( """Evt:%s, booking:%s, Admin API's getRoom operation got WebFault: %s""" % (confId, bookingId, e.fault.faultstring)) raise
def modifyRoom(cls, booking, oldBookingParams): # we extract the different parameters # We set the original conference id because the bookings can belong to more than one conference and being cloned # and it is used for the long name, we need to keep always the same confId confId = booking.getConference().getId() bookingId = booking.getId() roomId = booking.getRoomId() roomName = booking.getBookingParamByName("roomName") description = booking.getBookingParamByName("roomDescription") newOwner = booking.getOwnerObject() #an avatar object ownerAccountName = booking.getOwnerAccount() #a str oldOwner = oldBookingParams["owner"] #an IAvatarFossil fossil pin = booking.getPin() moderatorPin = booking.getModeratorPin() #we obtain the unicode object with the proper format for the room name roomNameForVidyo = VidyoTools.roomNameForVidyo(roomName) if isinstance(roomNameForVidyo, VidyoError): return roomNameForVidyo #we turn the description into a unicode object description = VidyoTools.descriptionForVidyo(description) if isinstance(description, VidyoError): return description #(the extension will not change) #we check if the owner has changed. If not, we reuse the same accountName useOldAccountName = True possibleLogins = [] if newOwner.getId() != oldOwner["id"]: useOldAccountName = False #we produce the list of possible account names. We will loop through them to attempt to create the room possibleLogins = VidyoTools.getAvatarLoginList(newOwner) if not possibleLogins: raise CollaborationException( _("The moderator has no login information")) # We check the moderator PIN is a 3-10 digit number if moderatorPin and (not moderatorPin.isdigit() or len(moderatorPin) < 3 or len(moderatorPin) > 10): return VidyoError("PINLength", "modify") roomModified = False loginToUse = 0 while not roomModified and (useOldAccountName or loginToUse < len(possibleLogins)): if not useOldAccountName: ownerAccountName = possibleLogins[loginToUse] newRoom = SOAPObjectFactory.createRoom(roomNameForVidyo, description, ownerAccountName, booking.getExtension(), pin, moderatorPin) try: AdminApi.updateRoom(roomId, newRoom) roomModified = True except WebFault, e: faultString = e.fault.faultstring if faultString.startswith('Room not exist for roomID'): return VidyoError("unknownRoom", "modify") elif faultString.startswith('Room exist for name'): return VidyoError("duplicated", "modify") elif faultString.startswith('Member not found for ownerName'): if useOldAccountName: #maybe the user was deleted between the time the room was created and now return VidyoError("badOwner", "modify") else: loginToUse = loginToUse + 1 elif faultString.startswith( 'PIN should be a 3-10 digit number'): return VidyoError("PINLength", "modify") else: Logger.get('Vidyo').exception( """Evt:%s, booking:%s, Admin API's updateRoom operation got WebFault: %s""" % (confId, bookingId, e.fault.faultstring)) raise
else: loginToUse = loginToUse + 1 elif faultString.startswith( 'PIN should be a 3-10 digit number'): return VidyoError("PINLength", "modify") else: Logger.get('Vidyo').exception( """Evt:%s, booking:%s, Admin API's updateRoom operation got WebFault: %s""" % (confId, bookingId, e.fault.faultstring)) raise #if we could not create the room, the owner did not have any Vidyo accounts if not roomModified and loginToUse == len(possibleLogins): return VidyoError("badOwner", "modify") # we retrieve the just created room; we need to do this because Vidyo will have # added extra data like the room id, the url try: modifiedRoom = AdminApi.getRoom(roomId) except WebFault, e: faultString = e.fault.faultstring if faultString.startswith('Room not found for roomID'): return VidyoError("unknownRoom", "modify") else: Logger.get('Vidyo').exception( """Evt:%s, booking:%s, Admin API's getRoom operation got WebFault: %s""" % (confId, bookingId, e.fault.faultstring)) raise
def createRoom(cls, booking): """ Attempts to create a public room in Vidyo. Returns None on success. Will also set booking.setAccountName() if success, with the Indico & Vidyo login used successfully. Returns a VidyoError instance if there are problems. :param booking: the CSBooking object inside which we try to create the room :type booking: MaKaC.plugins.Collaboration.Vidyo.collaboration.CSBooking """ # we extract the different parameters # We set the original conference id because the bookings can belong to more than one conference and being cloned # and it is used for the long name, we need to keep always the same confId confId = booking.getConference().getId() bookingId = booking.getId() roomName = booking.getBookingParamByName("roomName") description = booking.getBookingParamByName("roomDescription") owner = booking.getOwnerObject() pin = booking.getPin() moderatorPin = booking.getModeratorPin() #we obtain the unicode object with the proper format for the room name roomNameForVidyo = VidyoTools.roomNameForVidyo(roomName) if isinstance(roomNameForVidyo, VidyoError): return roomNameForVidyo #we turn the description into a unicode object description = VidyoTools.descriptionForVidyo(description) if isinstance(description, VidyoError): return description #we obtain the most probable extension #TODO: there's a length limit for extensions, check this baseExtension = getVidyoOptionValue("prefix") + confId extension = baseExtension extensionSuffix = 1 #we produce the list of possible account names. We will loop through them to attempt to create the room possibleLogins = VidyoTools.getAvatarLoginList(owner) if not possibleLogins: return VidyoError("userHasNoAccounts", "create") # We check the moderator PIN is a 3-10 digit number if moderatorPin and (not moderatorPin.isdigit() or len(moderatorPin) < 3 or len(moderatorPin) > 10): return VidyoError("PINLength", "create") roomCreated = False loginToUse = 0 while not roomCreated and loginToUse < len(possibleLogins): #we loop changing the ownerName and the extension until room is created newRoom = SOAPObjectFactory.createRoom(roomNameForVidyo, description, possibleLogins[loginToUse], extension, pin, moderatorPin) try: AdminApi.addRoom(newRoom) roomCreated = True except WebFault, e: faultString = e.fault.faultstring if faultString.startswith('Room exist for name'): if VidyoOperations.roomWithSameOwner( possibleLogins[loginToUse], roomNameForVidyo): return VidyoError("duplicatedWithOwner", "create") else: return VidyoError("duplicated", "create") elif faultString.startswith('Member not found for ownerName'): loginToUse = loginToUse + 1 elif faultString.startswith( 'PIN should be a 3-10 digit number'): return VidyoError("PINLength", "create") elif faultString.startswith('Room exist for extension'): extension = baseExtension + str(extensionSuffix) extensionSuffix = extensionSuffix + 1 else: Logger.get('Vidyo').exception( """Evt:%s, booking:%s, Admin API's addRoom operation got WebFault: %s""" % (confId, bookingId, e.fault.faultstring)) raise
class VidyoOperations(object): """ This class has several class methods, each of which represents a high-level operation, which sometimes involve several actual SOAP service calls. The objective is to not clutter the CSBooking methods with API logic. None of these methods should change the Indico DB, so they should not set any value on any object. """ @classmethod def roomWithSameOwner(cls, owner, roomName): # we retrieve the just created room; we need to do this because Vidyo will have # added extra data like the room id, the url searchFilter = SOAPObjectFactory.createFilter('admin', roomName) answer = AdminApi.getRooms(searchFilter) createdRooms = answer.room for room in createdRooms: if str(room.name) == roomName and str(room.ownerName) == owner: return room return None @classmethod def createRoom(cls, booking): """ Attempts to create a public room in Vidyo. Returns None on success. Will also set booking.setAccountName() if success, with the Indico & Vidyo login used successfully. Returns a VidyoError instance if there are problems. :param booking: the CSBooking object inside which we try to create the room :type booking: MaKaC.plugins.Collaboration.Vidyo.collaboration.CSBooking """ # we extract the different parameters # We set the original conference id because the bookings can belong to more than one conference and being cloned # and it is used for the long name, we need to keep always the same confId confId = booking.getConference().getId() bookingId = booking.getId() roomName = booking.getBookingParamByName("roomName") description = booking.getBookingParamByName("roomDescription") owner = booking.getOwnerObject() pin = booking.getPin() moderatorPin = booking.getModeratorPin() #we obtain the unicode object with the proper format for the room name roomNameForVidyo = VidyoTools.roomNameForVidyo(roomName) if isinstance(roomNameForVidyo, VidyoError): return roomNameForVidyo #we turn the description into a unicode object description = VidyoTools.descriptionForVidyo(description) if isinstance(description, VidyoError): return description #we obtain the most probable extension #TODO: there's a length limit for extensions, check this baseExtension = getVidyoOptionValue("prefix") + confId extension = baseExtension extensionSuffix = 1 #we produce the list of possible account names. We will loop through them to attempt to create the room possibleLogins = VidyoTools.getAvatarLoginList(owner) if not possibleLogins: return VidyoError("userHasNoAccounts", "create") # We check the moderator PIN is a 3-10 digit number if moderatorPin and (not moderatorPin.isdigit() or len(moderatorPin) < 3 or len(moderatorPin) > 10): return VidyoError("PINLength", "create") roomCreated = False loginToUse = 0 while not roomCreated and loginToUse < len(possibleLogins): #we loop changing the ownerName and the extension until room is created newRoom = SOAPObjectFactory.createRoom(roomNameForVidyo, description, possibleLogins[loginToUse], extension, pin, moderatorPin) try: AdminApi.addRoom(newRoom) roomCreated = True except WebFault, e: faultString = e.fault.faultstring if faultString.startswith('Room exist for name'): if VidyoOperations.roomWithSameOwner( possibleLogins[loginToUse], roomNameForVidyo): return VidyoError("duplicatedWithOwner", "create") else: return VidyoError("duplicated", "create") elif faultString.startswith('Member not found for ownerName'): loginToUse = loginToUse + 1 elif faultString.startswith( 'PIN should be a 3-10 digit number'): return VidyoError("PINLength", "create") elif faultString.startswith('Room exist for extension'): extension = baseExtension + str(extensionSuffix) extensionSuffix = extensionSuffix + 1 else: Logger.get('Vidyo').exception( """Evt:%s, booking:%s, Admin API's addRoom operation got WebFault: %s""" % (confId, bookingId, e.fault.faultstring)) raise #if we could not create the room, the owner did not have any Vidyo accounts if not roomCreated and loginToUse == len(possibleLogins): return VidyoError("badOwner", "create") # we retrieve the just created room; we need to do this because Vidyo will have # added extra data like the room id, the url searchFilter = SOAPObjectFactory.createFilter('admin', extension) answer = AdminApi.getRooms(searchFilter) createdRooms = answer.room for room in createdRooms: if str(room.extension) == extension: return room return None