def should_successfully_download_dir(self):
        local_dir = 'C:\\Development\\Tests'
        remote_dir = 'home/user/VIDEO/STEPICSTUDIO/tests'
        client = TabletClient()
        status = client.download_dir(remote_dir, local_dir)

        self.assertEqual(status.status, ExecutionStatus.SUCCESS)
Example #2
0
 def __init__(self):
     self.trigger_count = 0
     try:
         self.tablet_client = TabletClient(connect_timeout=0.5)
     except Exception as e:
         logger.error('Can\'t connect to tablet: %s', str(e))
         self.tablet_client = None
    def __init__(self):
        self.__command = settings.FFMPEG_TABLET_CMD
        self.__logger = logging.getLogger(
            'stepic_studio.video_recorders.tablet_recorder')
        self.last_processed_path = None
        self.last_processed_file = None

        try:
            self.__tablet_client = TabletClient(connect_timeout=10)
        except Exception as e:
            self.__logger.error('Can\'t initialize tablet client: %s', e)
            raise e
def collect_garbage():
    tablet_client = TabletClient()
    result_size = 0
    ss_count = 0
    from stepicstudio.models import SubStep
    for substep in SubStep.objects.all():
        if is_outdated(substep):
            status, size = tablet_client.delete_folder(substep.os_tablet_path)

            if status.status is ExecutionStatus.SUCCESS:
                ss_count += 1
                result_size += size
                logger.info(
                    'Tablet\'s directory deleted. (path: %s) \n Released memory: %s',
                    substep.os_tablet_path, bytes2human(size))

    tablet_client.close()
    logger.info('Collected %s of garbage (%s folders).\n GC delay: %s days.',
                bytes2human(result_size), ss_count,
                settings.GARBAGE_COLLECT_DELAY)
Example #5
0
def delete_tablet_lesson_files(lesson) -> InternalOperationResult:
    try:
        client = TabletClient()
        client.delete_folder_recursively(lesson.tablet_path)
        client.close()
        return InternalOperationResult(ExecutionStatus.SUCCESS)
    except Exception as e:
        logger.warning('Failed to remove lesson %s from tablet (id: %s): %s',
                       lesson.name, lesson.id, e)
        return InternalOperationResult(ExecutionStatus.FATAL_ERROR)
class TabletScreenRecorder(object):
    def __init__(self):
        self.__command = settings.FFMPEG_TABLET_CMD
        self.__logger = logging.getLogger(
            'stepic_studio.video_recorders.tablet_recorder')
        self.last_processed_path = None
        self.last_processed_file = None

        try:
            self.__tablet_client = TabletClient(connect_timeout=10)
        except Exception as e:
            self.__logger.error('Can\'t initialize tablet client: %s', e)
            raise e

    def start_recording(self, path: str,
                        filename: str) -> InternalOperationResult:
        if self.is_active():
            self.__logger.error(
                'Can\'t start FFMPEG for file %s: screen is acctually recording ',
                path + '/' + filename)
            return InternalOperationResult(ExecutionStatus.FATAL_ERROR,
                                           'Tablet is actually recording')

        try:
            self.__tablet_client.check_and_create_folder(path)
        except Exception as e:
            self.__logger.error('Error while creating remmote dir: %s', e)
            return InternalOperationResult(ExecutionStatus.FATAL_ERROR)

        command = settings.FFMPEG_TABLET_CMD + path + '/' + filename + ' 2< /dev/null &'

        try:
            self.__tablet_client.execute_remote(command)
        except Exception as e:
            self.__logger.error(
                'Screen recording start failed: %s; FFMPEG command: %s', e,
                command)
            return InternalOperationResult(ExecutionStatus.FATAL_ERROR)

        self.last_processed_file = filename
        self.last_processed_path = path
        self.__logger.info(
            'Successfully start screen recording (FFMPEG command: %s', command)
        return InternalOperationResult(ExecutionStatus.SUCCESS)

    def stop_recording(self) -> InternalOperationResult:
        if not self.is_active():
            self.__logger.warning(
                'Tablet screencast isn\'t active: can\'t stop non existing FFMPEG process'
            )
            return InternalOperationResult(ExecutionStatus.SUCCESS)

        command = 'pkill -f ffmpeg'

        for _ in range(0, ATTEMPTS_TO_STOP):
            try:
                #  read_output=True is using for synchronized execution
                self.__tablet_client.execute_remote(command,
                                                    allowable_code=1,
                                                    read_output=True)
            except Exception as e:
                self.__logger.error('Problems while stop screen recording: %s',
                                    e)
                return InternalOperationResult(ExecutionStatus.FATAL_ERROR)

            if not self.is_active():
                return InternalOperationResult(ExecutionStatus.SUCCESS)
            else:
                time.sleep(ATTEMPTS_PAUSE)

        self.__logger.error(
            'Can\'t stop screen recording process for %s seconds.',
            ATTEMPTS_PAUSE * ATTEMPTS_TO_STOP)
        return InternalOperationResult(ExecutionStatus.FIXABLE_ERROR)

    def is_active(self) -> bool:
        try:
            output = self.__tablet_client.execute_remote('ps -A | grep ffmpeg',
                                                         allowable_code=1,
                                                         read_output=True)
            return bool(output)  # equal to True if not None and not empty
        except Exception as e:
            self.__logger.warning('Can\'t get screen recorder status: %s', e)
            return False

    def download_last_recording(self, local_path: str):
        self.__tablet_client.download_file(self.last_processed_path,
                                           self.last_processed_file,
                                           local_path)
Example #7
0
def delete_tablet_substep_files(substep) -> InternalOperationResult:
    client = TabletClient()
    status = client.delete_file(substep.os_tablet_path)
    client.close()
    return status
Example #8
0
class SetStorageCapacityMiddleware(object):
    def __init__(self):
        self.trigger_count = 0
        try:
            self.tablet_client = TabletClient(connect_timeout=0.5)
        except Exception as e:
            logger.error('Can\'t connect to tablet: %s', str(e))
            self.tablet_client = None

    def process_response(self, request, response):
        if request.is_ajax():
            return response

        if not self.is_triggered():
            return response

        try:
            if hasattr(request, 'user') and \
                    request.user.is_authenticated():
                self.handle_server_space_info(request)
                self.handle_tablet_space_info(request)
            else:
                request.session['server_space_info'] = 'unknown'
                request.session['tablet_space_info'] = 'unknown'
                request.session['server_space_status'] = 'unknown'
                request.session['tablet_space_status'] = 'unknown'
        except Exception as e:
            logger.error('Exception handled while setting capacity info: %s',
                         str(e))
        return response

    def handle_server_space_info(self, request):
        try:
            user_server_path = UserProfile.objects.get(
                user=request.user.id).serverFilesFolder
            free_server_space, total_server_space = get_server_disk_info(
                user_server_path)
            request.session['server_space_info'] = bytes2human(free_server_space) + \
                                                   ' / ' + \
                                                   bytes2human(total_server_space)
            if free_server_space < settings.ERROR_CAPACITY:
                request.session['server_space_status'] = 'error'
                logger.warning(
                    'Critically low server disk space: free space: %s; total space: %s',
                    bytes2human(free_server_space),
                    bytes2human(total_server_space))
            elif free_server_space < settings.WARNING_CAPACITY:
                logger.warning(
                    'Low server disk space: free space: %s; total space: %s',
                    bytes2human(free_server_space),
                    bytes2human(total_server_space))
                request.session['server_space_status'] = 'warning'
            else:
                request.session['server_space_status'] = 'normal'
        except Exception as e:
            logger.warning(
                'Can\'t get information about server disk capacity: %s',
                str(e))
            request.session['server_space_info'] = 'unknown'
            request.session['server_space_status'] = 'unknown'

    def handle_tablet_space_info(self, request):
        try:
            if self.tablet_client is None:
                raise RuntimeError('Tablet client is dummy')
            tablet_free_space, total_tablet_space = self.tablet_client.get_disk_info(
            )
            request.session['tablet_space_info'] = bytes2human(tablet_free_space) + \
                                                   ' / ' + \
                                                   bytes2human(total_tablet_space)
            if tablet_free_space < settings.ERROR_CAPACITY:
                request.session['tablet_space_status'] = 'error'
                logger.warning(
                    'Critically low tablet disk capacity: free space: %s; total space: %s',
                    bytes2human(tablet_free_space),
                    bytes2human(total_tablet_space))
            elif tablet_free_space < settings.WARNING_CAPACITY:
                logger.warning(
                    'Low tablet disk capacity: free space: %s; total space: %s',
                    bytes2human(tablet_free_space),
                    bytes2human(total_tablet_space))
                request.session['tablet_space_status'] = 'warning'
            else:
                request.session['tablet_space_status'] = 'normal'
        except Exception as e:
            logger.exception(
                'Can\'t get information about tablet disk capacity: %s',
                str(e))
            request.session['tablet_space_info'] = 'unknown'
            request.session['tablet_space_status'] = 'unknown'

    def is_triggered(self):
        self.trigger_count = (self.trigger_count % POLL_FREQUENCY) + 1
        return self.trigger_count == 1