Source code for dilium_client.node

"""
-----------
Dilium node
-----------
"""

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

from contextlib import contextmanager
import logging
import random
import signal
import tempfile
import time

from pylru import lrudecorator

from dilium_client._ansible import Executor
from dilium_client._selenium import Chrome

from . import config, utils

LOGGER = logging.getLogger(__name__)


[docs]class Node(object): """Remote node with requested browser. Args: client (Client): Dilium client. """ def __init__(self, client): self._client = client self._display = random.randint(1, config.MAX_DISPLAY) self._video_path = None self._driver_pid = None self._video_pid = None self._xvfb_pid = None
[docs] def get_browser(self, *args, **kwgs): """Get browser on node. Args: *args (optional): ``*args`` of browser instantiation. **kwgs (optional): ``**kwgs`` of browser instantiation. """ browser = { config.CHROME: Chrome, }[self._client.browser_name] return browser(self, *args, **kwgs)
[docs] def start_video(self, width, height): """Start video capturing. Args: width (int): Video width. height (int): Video height. """ if self._video_pid: LOGGER.warn('Video capturing is launched already') return self._video_path = tempfile.mktemp() + '.mp4' try: self._video_pid = utils.get_pid( self.remote_exec.avconv( self._video_path, self._display, width, height)) time.sleep(1) except: self._video_path = None raise
[docs] def stop_video(self): """Stop video capturing.""" if not self._video_pid: LOGGER.warn('Video capturing isn\'t launched still') return try: self.remote_exec.kill(self._video_pid) time.sleep(1) finally: self._video_pid = None
@contextmanager
[docs] def capture_video(self, width, height): """Capture video in context. Args: width (int): Video width. height (int): Video height. """ self.start_video(width, height) try: yield finally: self.stop_video()
[docs] def download_video(self, file_path=None): """Download captured video. Args: file_path (str, optional): Path to download video. Returns: str: Path of downloaded video. """ file_path = file_path or tempfile.mkstemp()[1] self.remote_exec.download(self.video_path, file_path) return file_path
[docs] def start_xvfb(self, width, height): """Start virtual display. Args: width (int): Screen width. height (int): Screen height. """ if self._xvfb_pid: LOGGER.warn('Xvfb is launched already') return self._xvfb_pid = utils.get_pid( self.remote_exec.xvfb(self._display, width, height, options=["-noreset", "-ac"])) time.sleep(1)
[docs] def stop_xvfb(self): """Stop virtual display.""" if not self._xvfb_pid: LOGGER.warn('Xvfb isn\'t launched still') return try: self.remote_exec.kill(self._xvfb_pid) time.sleep(1) finally: self._xvfb_pid = None
@contextmanager
[docs] def inside_xvfb(self, width, height): """Launch virtual display in context. Args: width (int): Screen width. height (int): Screen height. """ self.start_xvfb(width, height) try: yield finally: self.stop_xvfb()
[docs] def start_webdriver(self): """Start remote webdriver.""" if self._driver_pid: LOGGER.warn('Webdriver is launched already') return port = random.randint(*config.PORT_RANGE) chrome_cmd = 'chromedriver --port={} --whitelisted-ips=""'.format(port) driver_cmd = { config.CHROME: chrome_cmd, }[self._client.browser_name] env = {'DISPLAY': ':{}'.format(self._display)} self._driver_pid = utils.get_pid( self.remote_exec.webdriver(driver_cmd, env=env)) time.sleep(1) self._webdriver_url = 'http://{}:{}'.format(self._client.host, port)
[docs] def stop_webdriver(self): """Stop remote webdriver.""" if not self._driver_pid: LOGGER.warn('Webdriver isn\'t launched still') return try: self.remote_exec.kill(self._driver_pid, signal.SIGTERM) time.sleep(1) finally: self._driver_pid = None
@property @lrudecorator(None) def remote_exec(self): """Remote ansible executor.""" return Executor(self._client.host) @property def webdriver_url(self): """Launched webdriver url.""" assert self._webdriver_url return self._webdriver_url @property def video_path(self): """Remote path to captured video.""" assert self._video_path return self._video_path