Пример #1
0
def get_room_status(room_name, room_special_name=None):
    """Get the status of a room given its name.

    :param room_name: str -- The name of the room whose status is fetched
    :param room_special_name: str -- The prettier name of a room, used in the
        error messages. For example "IT-Amphitheatre" for the room `31-3-004`.
        Defaults to the room's name

    :returns: dict -- the status of the room with the following information:
        - `vc_room_name`: The name of the vc_room the room is connected to or
        `None` if the room is not connected.
        - `connected`: `True` if the room is connected, `False` otherwise
        - `service_type`: The type of service, given by RAVEM. Usually '"vidyo"'
        or `"other"`
        - `room_endpoint`: prefixed H323 IP or Vidyo user name of the room.
    """
    room_special_name = room_special_name or room_name
    response = get_endpoint_status(room_name)
    if 'error' in response:
        RavemPlugin.logger.error("Failed to get status of room %s with error: %s", room_special_name, response['error'])
        raise RavemException(_("Failed to get status of room {room} with error:\n{response[error]}")
                             .format(room=room_special_name, response=response))

    result = response['result']
    if result == 'Service not found':
        RavemPlugin.logger.error("Vidyo is not supported in the room %s", room_special_name)
        raise RavemException(_("Vidyo is not supported in the room {room}").format(room=room_special_name))

    status = next(s for s in result['services'] if s['name'] == 'videoconference')
    return {
        'vc_room_name': status['event_name'],
        'connected': status['status'] == 1,
        'service_type': status['event_type'],
        'room_endpoint': get_room_endpoint(result)
    }
Пример #2
0
def disconnect_room(room_name, vc_room, force=False, room_verbose_name=None):
    """Disconnect a room given its name from a given vc_room.

    If a `RavemException` is raised it is important to verify the
    `reason` attribute of the exception.
    If the room is already disconnected, the `reason` will be:
    `"already-disconnected"`.
    If the room is connected to another VC room and we are not forcing
    the disconnection, the `reason` will be: `"connected-other"`.

    Forcing the disconnection (`force=True`) will force the room to disconnect
    from the VC room it is connected to, regardless of the given VC room.

    :param room_name: str -- The name of the room to disconnect
    :param vc_room: VCRoom -- The VC room instance to disconnect from the room.
    :param force: bool -- Whether to force the disconnection of the room.
        Defaults to `False`
    :param room_verbose_name: str -- The prettier name of a room, used in the
        error messages.

    :raises: RavemException
    """
    _room_name = room_verbose_name or room_name
    status = get_room_status(room_name)
    _ensure_room_service(room_name, vc_room.type, status['service_type'])
    service_api = get_api(vc_room.type)
    vc_room_id = service_api.get_room_id(vc_room.data)
    if not status['connected']:
        raise RavemException(
            _("The room {room} is already disconnected.").format(room=_room_name),
            'already-disconnected'
        )
    if status['vc_room_id'] != vc_room_id:
        if not force:
            raise RavemException(
                _("The room {room} is connected to another videoconference room: {vc_room}")
                .format(room=_room_name, vc_room=status['vc_room_id']),
                'connected-other'
            )
        else:
            RavemPlugin.logger.info("Force disconnect of room %s from videoconference %s",
                                    _room_name, status['vc_room_id'])

    response = service_api.disconnect_endpoint(room_name, vc_room_id)

    if response.get('error'):
        if response['error'] == 'Call already disconnected':
            raise RavemException(
                _('The room {room} is already disconnected.').format(room=_room_name),
                'already-disconnected'
            )

        RavemPlugin.logger.error("Failed to disconnect the room %s from the videoconference room %s with error: %s",
                                 _room_name, vc_room_id, response['error'])
        raise RavemException(
            _("Failed to disconnect the room {room} from the videoconference room {vc_room} with error: "
              "{response[error]}").format(room=_room_name, vc_room=vc_room_id, response=response)
        )
    return response.get('success', False)
Пример #3
0
def disconnect_room(room_name, vc_room, force=False, room_special_name=None):
    """Disconnect a room given its name from a given vc_room.

    If a `RavemOperationException` is raised it is important to verify the
    `reason` attribute of the exception.
    If the room is already disconnected, the `reason` will be:
    `"already-disconnected"`.
    If the room is connected to another VC room and we are not forcing
    the disconnection, the `reason` will be: `"connected-other"`.

    Forcing the disconnection (`force=True`) will force the room to disconnect
    from the VC room it is connected to, regardless of the given VC room.

    :param room_name: str -- The name of the room to disconnect
    :param vc_room: VCRoom -- The VC room instance to disconnect from the room.
    :param force: bool -- Whether to force the disconnection of the room.
        Defaults to `False`
    :param room_special_name: str -- The prettier name of a room, used in the
        error messages. For example "IT-Amphitheatre" for the room `31-3-004`.
        Defaults to the room's name

    :raises: RavemOperationException, RavemException
    """
    room_special_name = room_special_name or room_name
    status = get_room_status(room_name, room_special_name=room_special_name)
    if not status['connected']:
        raise RavemOperationException(
            _("The room {room} is already disconnected.").format(
                room=room_special_name), 'already-disconnected')
    if status['vc_room_name'] != vc_room.name:
        if not force:
            raise RavemOperationException(
                _("The room {room} is connected to an other Vidyo room: {status[vc_room_name]}"
                  ).format(room=room_special_name, status=status),
                'connected-other')
        else:
            RavemPlugin.logger.info(
                "Force disconnect of room %s from vc_room %s "
                "(expected to disconnect from vc_room %s)", room_special_name,
                status['vc_room_name'], vc_room.name)

    response = disconnect_endpoint(room_name, status['vc_room_name'],
                                   status['service_type'])

    if 'error' in response:
        if response['error'] == 'Call already disconnected':
            raise RavemOperationException(
                _("The room {room} is already disconnected.").format(
                    room=room_special_name), 'already-disconnected')

        RavemPlugin.logger.error(
            "Failed to disconnect the room %s from the Vidyo room %s with error: %s",
            room_special_name, vc_room.name, response['error'])
        raise RavemException(
            _("Failed to disconnect the room {room} from the Vidyo room {vc_room.name} with error: {response[error]}"
              ).format(room=room_special_name,
                       vc_room=vc_room,
                       response=response))
Пример #4
0
 def get_event_vc_room(self, id_):
     event_vc_room = VCRoomEventAssociation.query.get(id_)
     if not event_vc_room:
         raise NotFound(_("Event VC Room not found for id {id}").format(id=id_))
     if not event_vc_room.link_object:
         raise IndicoError(
             _("Event VC Room ({id}) is not linked to anything").format(id=id_)
         )
     return event_vc_room
Пример #5
0
    def _process_args(self):
        id_ = request.view_args['event_vc_room_id']
        self.event_vc_room = self.get_event_vc_room(id_)

        event_id = request.view_args['event_id']
        event = self.event_vc_room.link_object.event
        if not event:
            raise IndicoError(_("Event VC Room ({id}) does not have an event").format(id=id_))
        if event.id != event_id:
            raise IndicoError(_("Event VC Room ({id}) does not have an event with the id {conf.id}")
                              .format(id=id_, conf=event))

        self.room = self.event_vc_room.link_object.room if self.event_vc_room.link_object else None
        if not self.room:
            raise IndicoError(_("Event VC Room ({id}) is not linked to an event with a room").format(id=id_))
        if not self.room.name:
            raise IndicoError(_("Event VC Room ({id}) is not linked to an event with a valid room").format(id=id_))
Пример #6
0
def _ensure_room_service(room_name, room_service, device_type):
    """Ensure the virtual room conference service matches with what the physical room supports"""
    if room_service and device_type != room_service:
        RavemPlugin.logger.error(
            "%s is not supported in the room %s", room_service, room_name
        )
        raise RavemException(
            _("{service} is not supported in the room {room}").format(
                service=room_service, room=room_name
            )
        )
Пример #7
0
    def _process_args(self):
        id_ = request.view_args['event_vc_room_id']
        self.event_vc_room = VCRoomEventAssociation.find_one(id=id_)
        if not self.event_vc_room:
            raise NotFound(_("Event VC Room not found for id {id}").format(id=id_))

        if not self.event_vc_room.link_object:
            raise IndicoError(_("Event VC Room ({id}) is not linked to anything").format(id=id_))

        event_id = int(request.view_args['confId'])
        event = self.event_vc_room.link_object.event
        if not event:
            raise IndicoError(_("Event VC Room ({id}) does not have an event").format(id=id_))

        if event.id != event_id:
            raise IndicoError(_("Event VC Room ({id}) does not have an event with the id {conf.id}")
                              .format(id=id_, conf=event))

        room = self.event_vc_room.link_object.room if self.event_vc_room.link_object else None
        if not room:
            raise IndicoError(_("Event VC Room ({id}) is not linked to an event with a room").format(id=id_))

        self.room_name = room.generate_name()
        self.room_special_name = room.name

        if not self.room_name:
            raise IndicoError(_("Event VC Room ({id}) is not linked to an event with a valid room").format(id=id_))

        if not self.room_special_name:
            self.room_special_name = self.room_name
Пример #8
0
def get_room_status(room_name, room_verbose_name=None):
    """Get the status of a room given its name.

    :param room_name: str -- The name of the room whose status is fetched
    :param room_verbose_name: str -- The prettier name of a room, used in the
        error messages. For example "IT-Amphitheatre" for the room `31-3-004`.
        Defaults to the room's name

    :returns: dict -- the status of the room with the following information:
        - `room_name`: The room identifier
        - `vc_room_id`: The id of the vc_room the room is connected to or
        `None` if the room is not connected.
        - `service_type`: The type of service, given by RAVEM. Usually '"zoom"'
        or `"other"`
        - `connected`: `True` if the room is connected, `False` otherwise
    """
    _room_name = room_verbose_name or room_name
    response = BaseAPI.get_endpoint_status(room_name)
    if response.get("error"):
        RavemPlugin.logger.error(
            "Failed to get status of room %s with error: %s",
            _room_name,
            response["error"],
        )
        raise RavemException(
            _(
                "Failed to get status of room {room} with error: {response[error]}"
            ).format(room=_room_name, response=response)
        )
    status = next(s for s in response['services'] if s['name'] == 'videoconference')
    return {
        'room_name': response['roomName'],
        'vc_room_id': status['eventName'],
        # As per RAVEM api v2, deviceType is identified per room, instead of per room service
        'service_type': response['deviceType'],
        'connected': status['status']
    }
Пример #9
0
class SettingsForm(IndicoForm):  # pragma: no cover
    debug = BooleanField(_('Debug mode'), widget=SwitchWidget(),
                         description=_("If enabled, no actual connect/disconnect requests are sent"),)
    api_endpoint = URLField(_('API endpoint'), [DataRequired()], filters=[lambda x: x.rstrip('/') + '/'],
                            description=_('The endpoint for the RAVEM API'))
    username = StringField(_('Username'), [DataRequired()],
                           description=_('The username used to connect to the RAVEM API'))
    password = IndicoPasswordField(_('Password'), [DataRequired()], toggle=True,
                                   description=_('The password used to connect to the RAVEM API'))
    prefix = IntegerField(_('Room IP prefix'), [NumberRange(min=0)],
                          description=_('IP prefix to connect a room to a Vidyo room.'))
    timeout = IntegerField(_('Timeout'), [NumberRange(min=0)],
                           description=_('The amount of time in seconds to wait for RAVEM to reply<br>'
                                         '(0 to disable the timeout)'))
    polling_limit = IntegerField(_('Polling limit'), [NumberRange(min=1)],
                                 description=_('The maximum number of time Indico should poll RAVEM for the status of '
                                               'an operation before considering it as failed<br>'
                                               '(delete the cached var.js to take effect)'))
    polling_interval = IntegerField(_('Polling interval'), [NumberRange(min=1000)],
                                    description=_('The delay between two polls in ms, at least 1000 ms<br>'
                                                  '(delete the cached var.js to take effect)'))
Пример #10
0
class SettingsForm(IndicoForm):  # pragma: no cover
    debug = BooleanField(_('Debug mode'), widget=SwitchWidget(),
                         description=_('If enabled, no actual connect/disconnect requests are sent'),)
    api_endpoint = URLField(_('API endpoint'), [DataRequired()], filters=[lambda x: x.rstrip('/') + '/'],
                            description=_('The endpoint for the RAVEM API'))
    access_token = IndicoPasswordField(_('Access token'), [DataRequired()], toggle=True,
                                       description=_('The access token used to connect to the RAVEM API'))
    timeout = IntegerField(_('Timeout'), [NumberRange(min=0)],
                           description=_('The amount of time in seconds to wait for RAVEM to reply<br>'
                                         '(0 to disable the timeout)'))
    polling_limit = IntegerField(_('Polling limit'), [NumberRange(min=1)],
                                 description=_('The maximum number of time Indico should poll RAVEM for the status of '
                                               'an operation before considering it as failed<br>'
                                               '(delete the cached var.js to take effect)'))
    polling_interval = IntegerField(_('Polling interval'), [NumberRange(min=1000)],
                                    description=_('The delay between two polls in ms, at least 1000 ms<br>'
                                                  '(delete the cached var.js to take effect)'))
    room_feature = QuerySelectField(_('Room feature'), [DataRequired()], allow_blank=True,
                                    query_factory=lambda: RoomFeature.query, get_label='title',
                                    description=_('The room equipment feature for videoconference capable rooms'))
Пример #11
0
def connect_room(room_name, vc_room, force=False, room_special_name=None):
    """Connects a room given its name with a given vc_room.

    If a `RavemOperationException` is raised it is important to verify the
    `reason` attribute of the exception.
    If the room is already connected to the given VC room, the `reason` will be:
    `"already-connected"`.
    If the room is already connected to another VC room and we are not forcing
    the connection, the `reason` will be: `"connected-other"`.

    Forcing the connection (`force=True`) means disconnecting the room from the
    VC room it is currently connected (if it is connected to a different VC room
    than the given one) This option does not guarantee to establish the
    connection as RAVEM might fail to disconnect the room or connect it
    afterwards to the new VC room.

    This operation will also take time as RAVEM is unable to indicate us if the
    disconnection was successful. It is thus required to poll RAVEM. The amount
    of polls and interval between them is defined in the settings. Note that a
    failure to disconnect might simply be slowness in the network coupled with
    aggressive polling settings which fail to poll the expected status in time.

    :param room_name: str -- The name of the room to connect
    :param vc_room: VCRoom -- The VC room instance to connect with the room.
    :param force: bool -- Whether to force the connection between the room and
        the VC room. Defaults to `False`
    :param room_special_name: str -- The prettier name of a room, used in the
        error messages. For example "IT-Amphitheatre" for the room `31-3-004`.
        Defaults to the room's name

    :raises: RavemOperationException, RavemException
    """
    room_special_name = room_special_name or room_name
    status = get_room_status(room_name, room_special_name=room_special_name)
    if status['connected']:
        if status['vc_room_name'] == vc_room.name:
            raise RavemOperationException(
                _("The room {room} is already connected to the vidyo room {vc_room.name}"
                  ).format(room=room_special_name, vc_room=vc_room),
                'already-connected')
        if not force:
            raise RavemOperationException(
                _("The room {room} is connected to an other Vidyo room: {status[vc_room_name]}"
                  ).format(room=room_special_name, status=status),
                'connected-other')
        disconnect_response = disconnect_endpoint(room_name,
                                                  status['vc_room_name'],
                                                  status['service_type'])
        if 'error' in disconnect_response:
            RavemPlugin.logger.error(
                "Failed to disconnect the room %s from the Vidyo room %s with error: %s",
                room_special_name, status['vc_room_name'],
                disconnect_response['error'])
            raise RavemException(
                _("Failed to disconnect the room {room} from the Vidyo room {status[vc_room_name]} with error: "
                  "{response[error]}").format(room=room_special_name,
                                              status=status,
                                              response=disconnect_response))

        # A "success" response from RAVEM doesn't mean the room is disconnected.
        # We need to poll RAVEM for the status of the room.

        # ms in settings but time.sleep takes sec
        polling_interval = RavemPlugin.settings.get(
            'polling_interval') / 1000.0
        for attempt in xrange(RavemPlugin.settings.get('polling_limit')):
            status = get_room_status(room_name,
                                     room_special_name=room_special_name)
            if not status['connected']:
                break
            sleep(polling_interval)
        else:
            RavemPlugin.logger.error(
                "Failed to disconnect the room %s from the Vidyo room %s with an unknown error",
                room_special_name, vc_room.name)
            raise RavemException(
                _("Failed to disconnect the room {room} from the Vidyo room {vc_room.name} with "
                  "an unknown error").format(room=room_special_name,
                                             vc_room=vc_room))

    response = connect_endpoint(vc_room.data['vidyo_id'],
                                status['room_endpoint'])

    if 'error' in response:
        RavemPlugin.logger.error(
            "Failed to connect the room %s to the Vidyo room %s with error: %s",
            room_special_name, vc_room.name, response['error'])
        raise RavemException(
            _("Failed to connect the room {room} to the Vidyo room {vc_room.name} with error: {response[error]}"
              ).format(room=room_special_name,
                       vc_room=vc_room,
                       response=response))
Пример #12
0
 def _check_access(self):
     if not has_access(self.event_vc_room):
         raise RavemException(_("Not authorized to access the room with RAVEM"))