mirror of
https://github.com/lucaspalomodevelop/indico-plugins.git
synced 2026-03-13 07:29:39 +00:00
VC/Vidyo: Add Vidyo room clean-up task + CLI
Added command to list Vidyo rooms, unit tests
This commit is contained in:
parent
352bd064c0
commit
776c484fb0
71
vc_vidyo/indico_vc_vidyo/cli.py
Normal file
71
vc_vidyo/indico_vc_vidyo/cli.py
Normal file
@ -0,0 +1,71 @@
|
||||
# This file is part of Indico.
|
||||
# Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN).
|
||||
#
|
||||
# Indico is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# Indico is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Indico; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import sys
|
||||
|
||||
from dateutil import rrule
|
||||
from flask_script import Manager
|
||||
from terminaltables import AsciiTable
|
||||
|
||||
from indico.core.db import db, DBMgr
|
||||
from indico.core.db.sqlalchemy.util.session import update_session_options
|
||||
from indico.modules.scheduler import Client
|
||||
from indico.modules.vc.models.vc_rooms import VCRoom, VCRoomStatus
|
||||
|
||||
from indico_vc_vidyo.task import VidyoCleanupTask
|
||||
|
||||
cli_manager = Manager(usage="Manages the Vidyo plugin")
|
||||
|
||||
|
||||
@cli_manager.command
|
||||
@cli_manager.option('--deleted', action='store_true')
|
||||
@cli_manager.option('--created', action='store_true')
|
||||
def rooms(deleted=False, created=False):
|
||||
"""Lists all Vidyo rooms"""
|
||||
|
||||
room_query = VCRoom.find(type='vidyo')
|
||||
table_data = [['ID', 'Name', 'Status', 'Vidyo ID', 'Extension']]
|
||||
|
||||
if deleted:
|
||||
room_query = room_query.filter(VCRoom.status == VCRoomStatus.deleted)
|
||||
if created:
|
||||
room_query = room_query.filter(VCRoom.status == VCRoomStatus.created)
|
||||
|
||||
for room in room_query:
|
||||
table_data.append([unicode(room.id), room.name, room.status.name,
|
||||
unicode(room.data['vidyo_id']), unicode(room.vidyo_extension.extension)])
|
||||
|
||||
table = AsciiTable(table_data)
|
||||
table.justify_columns[4] = 'right'
|
||||
print table.table
|
||||
|
||||
|
||||
@cli_manager.command
|
||||
def create_task(interval):
|
||||
"""Creates a Vidyo cleanup task running every N days"""
|
||||
update_session_options(db)
|
||||
try:
|
||||
interval = int(interval)
|
||||
if interval < 1:
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
print 'Invalid interval, must be a number >=1'
|
||||
sys.exit(1)
|
||||
with DBMgr.getInstance().global_connection(commit=True):
|
||||
Client().enqueue(VidyoCleanupTask(rrule.DAILY, interval=interval))
|
||||
print 'Task created'
|
||||
@ -24,7 +24,7 @@ from wtforms.fields.simple import StringField
|
||||
from wtforms.validators import NumberRange, DataRequired
|
||||
|
||||
from indico.core.config import Config
|
||||
from indico.core.plugins import IndicoPlugin, url_for_plugin, IndicoPluginBlueprint
|
||||
from indico.core.plugins import IndicoPlugin, url_for_plugin, IndicoPluginBlueprint, wrap_cli_manager
|
||||
from indico.modules.vc.exceptions import VCRoomError, VCRoomNotFoundError
|
||||
from indico.modules.vc import VCPluginSettingsFormBase, VCPluginMixin
|
||||
from indico.modules.vc.views import WPVCManageEvent, WPVCEventPage
|
||||
@ -34,6 +34,7 @@ from indico.web.forms.fields import IndicoPasswordField
|
||||
from indico.web.forms.widgets import CKEditorWidget
|
||||
|
||||
from indico_vc_vidyo.api import AdminClient, APIException, RoomNotFoundAPIException
|
||||
from indico_vc_vidyo.cli import cli_manager
|
||||
from indico_vc_vidyo.forms import VCRoomForm, VCRoomAttachForm
|
||||
from indico_vc_vidyo.util import iter_user_identities, iter_extensions, update_room_from_obj
|
||||
from indico_vc_vidyo.models.vidyo_extensions import VidyoExtension
|
||||
@ -275,12 +276,15 @@ class VidyoPlugin(VCPluginMixin, IndicoPlugin):
|
||||
client = AdminClient(self.settings)
|
||||
return client.get_room(vc_room.data['vidyo_id'])
|
||||
|
||||
def get_blueprints(self):
|
||||
return IndicoPluginBlueprint('vc_vidyo', __name__)
|
||||
|
||||
def register_assets(self):
|
||||
self.register_css_bundle('vc_vidyo_css', 'css/vc_vidyo.scss')
|
||||
self.register_js_bundle('vc_vidyo_js', 'js/vc_vidyo.js')
|
||||
|
||||
def get_blueprints(self):
|
||||
return IndicoPluginBlueprint('vc_vidyo', __name__)
|
||||
def add_cli_command(self, manager):
|
||||
manager.add_command('vidyo', wrap_cli_manager(cli_manager, self))
|
||||
|
||||
def get_vc_room_form_defaults(self, event):
|
||||
defaults = super(VidyoPlugin, self).get_vc_room_form_defaults(event)
|
||||
|
||||
82
vc_vidyo/indico_vc_vidyo/task.py
Normal file
82
vc_vidyo/indico_vc_vidyo/task.py
Normal file
@ -0,0 +1,82 @@
|
||||
# This file is part of Indico.
|
||||
# Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN).
|
||||
#
|
||||
# Indico is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# Indico is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Indico; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
import sqlalchemy
|
||||
from sqlalchemy.sql.expression import cast
|
||||
|
||||
from indico.core.db import db
|
||||
from indico.modules.vc.models.vc_rooms import VCRoomEventAssociation, VCRoom, VCRoomStatus
|
||||
from indico.modules.fulltextindexes.models.events import IndexedEvent
|
||||
from indico.modules.scheduler.tasks.periodic import PeriodicUniqueTask
|
||||
from indico.util.date_time import now_utc
|
||||
from indico.util.struct.iterables import committing_iterator
|
||||
from indico_vc_vidyo.api import RoomNotFoundAPIException
|
||||
|
||||
|
||||
def find_old_vidyo_rooms(max_room_event_age):
|
||||
"""Finds all Vidyo rooms that are:
|
||||
- linked to no events
|
||||
- linked only to events whose start date precedes today - max_room_event_age days
|
||||
"""
|
||||
recently_used = db.session.query(VCRoom.id).filter(
|
||||
VCRoom.type == 'vidyo',
|
||||
IndexedEvent.end_date > (now_utc() - timedelta(days=max_room_event_age))
|
||||
).join(VCRoomEventAssociation).join(
|
||||
IndexedEvent, IndexedEvent.id == cast(VCRoomEventAssociation.event_id, sqlalchemy.String)
|
||||
).group_by(VCRoom.id)
|
||||
|
||||
# non-deleted rooms with no recent associations
|
||||
return VCRoom.find(VCRoom.status != VCRoomStatus.deleted, ~VCRoom.id.in_(recently_used)).all()
|
||||
|
||||
|
||||
class VidyoCleanupTask(PeriodicUniqueTask):
|
||||
"""Gets rid of 'old' Vidyo rooms (not used in recent events)
|
||||
"""
|
||||
DISABLE_ZODB_HOOK = True
|
||||
|
||||
@property
|
||||
def logger(self):
|
||||
return self.getLogger()
|
||||
|
||||
def run(self):
|
||||
from indico_vc_vidyo.plugin import VidyoPlugin
|
||||
|
||||
plugin = VidyoPlugin.instance # RuntimeError if not active
|
||||
with plugin.plugin_context():
|
||||
|
||||
max_room_event_age = plugin.settings.get('num_days_old')
|
||||
|
||||
self.logger.info('Deleting Vidyo rooms that are not used or linked to events all older than {} days'.format(
|
||||
max_room_event_age))
|
||||
|
||||
candidate_rooms = find_old_vidyo_rooms(max_room_event_age)
|
||||
|
||||
self.logger.info('{} rooms found'.format(len(candidate_rooms)))
|
||||
|
||||
for vc_room in committing_iterator(candidate_rooms, n=20):
|
||||
try:
|
||||
plugin.delete_room(vc_room, None)
|
||||
self.logger.info('Room {} deleted from Vidyo server'.format(vc_room))
|
||||
vc_room.status = VCRoomStatus.deleted
|
||||
except RoomNotFoundAPIException:
|
||||
self.logger.warning('Room {} had been already deleted from the Vidyo server'.format(vc_room))
|
||||
vc_room.status = VCRoomStatus.deleted
|
||||
except:
|
||||
self.logger.exception('Impossible to delete Vidyo room {}'.format(vc_room))
|
||||
@ -32,6 +32,7 @@ setup(
|
||||
platforms='any',
|
||||
install_requires=[
|
||||
'indico>=1.9.1',
|
||||
'terminaltables==1.0.2',
|
||||
'suds-jurko'
|
||||
],
|
||||
classifiers=[
|
||||
|
||||
91
vc_vidyo/tests/task_test.py
Normal file
91
vc_vidyo/tests/task_test.py
Normal file
@ -0,0 +1,91 @@
|
||||
# This file is part of Indico.
|
||||
# Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN).
|
||||
#
|
||||
# Indico is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# Indico is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Indico; if not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
import pytest
|
||||
|
||||
from indico.modules.fulltextindexes.models.events import IndexedEvent
|
||||
from indico.modules.vc.models.vc_rooms import VCRoom, VCRoomEventAssociation, VCRoomStatus, VCRoomLinkType
|
||||
from indico_vc_vidyo.models.vidyo_extensions import VidyoExtension
|
||||
|
||||
|
||||
class DummyEvent(object):
|
||||
def __init__(self, id_, title, end_date):
|
||||
self.id = id_
|
||||
self.title = title
|
||||
self.end_date = end_date
|
||||
|
||||
def getEndDate(self):
|
||||
return self.end_date
|
||||
|
||||
def getId(self):
|
||||
return self.id
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def create_dummy_room(db, dummy_user):
|
||||
"""Returns a callable which lets you create dummy Vidyo room occurrences"""
|
||||
def _create_room(name, extension, owner, data, **kwargs):
|
||||
vc_room = VCRoom(
|
||||
name=name,
|
||||
data=data,
|
||||
type="vidyo",
|
||||
status=kwargs.pop('status', VCRoomStatus.created),
|
||||
created_by_id=kwargs.pop('created_by_id', dummy_user.id),
|
||||
**kwargs)
|
||||
db.session.add(vc_room)
|
||||
db.session.flush()
|
||||
extension = VidyoExtension(
|
||||
vc_room_id=vc_room.id,
|
||||
extension=extension,
|
||||
owned_by_id=owner.id
|
||||
)
|
||||
vc_room.vidyo_extension = extension
|
||||
return vc_room
|
||||
|
||||
return _create_room
|
||||
|
||||
|
||||
def test_room_cleanup(create_dummy_room, dummy_user, freeze_time, db):
|
||||
"""Test that 'old' Vidyo rooms are correctly detected"""
|
||||
freeze_time(datetime(2015, 2, 1))
|
||||
events = {}
|
||||
|
||||
for id_, args in enumerate((('Event one', datetime(2012, 1, 1)),
|
||||
('Event two', datetime(2013, 1, 1)),
|
||||
('Event three', datetime(2014, 1, 1)),
|
||||
('Event four', datetime(2015, 1, 1))), start=1):
|
||||
event = DummyEvent(id_, *args)
|
||||
events[id_] = event
|
||||
idx = IndexedEvent(id=id_, title=args[0], end_date=args[1], start_date=args[1])
|
||||
db.session.add(idx)
|
||||
|
||||
for id_, args in enumerate(((1234, 5678, (1, 2, 3, 4)),
|
||||
(1235, 5679, (1, 2)),
|
||||
(1235, 5679, (2,)),
|
||||
(1236, 5670, (4,)),
|
||||
(1237, 5671, ())), start=1):
|
||||
room = create_dummy_room('test_room_{}'.format(id_), args[0], dummy_user, {
|
||||
'vidyo_id': args[1]
|
||||
})
|
||||
for evt_id in args[2]:
|
||||
VCRoomEventAssociation(vc_room=room, event=events[evt_id], link_type=VCRoomLinkType.event)
|
||||
db.session.flush()
|
||||
|
||||
from indico_vc_vidyo.task import find_old_vidyo_rooms
|
||||
|
||||
assert [r.id for r in find_old_vidyo_rooms(180)] == [2, 3, 5]
|
||||
Loading…
x
Reference in New Issue
Block a user