Exemple #1
0
def _process_loop(cls, parent_pid):
    """Child process loop which handles start/stop events and exceptions."""
    with _child_process_wrapper(parent_pid, cls.process_name, cls.device_name,
                                cls._exception_queue):
        gdm_logger.initialize_child_process_logging(cls.logging_queue)
        try:
            cls._start_event.set()
        except Exception as err:
            stack_trace = traceback.format_exc()
            gdm_logger.get_logger().info(
                "Device {} Process {} error {!r} start event error. {}".format(
                    cls.device_name, cls.process_name, err, stack_trace))
        running = cls._pre_run_hook()
        while running and _parent_is_alive(parent_pid):
            try:
                if cls._terminate_event.is_set():
                    cls._terminate_event.clear()
                    break
            except IOError:  # manager shutdown
                break
            running = cls._do_work()
    try:
        cls._stop_event.set()
    except IOError:  # manager shutdown
        pass
    cls._post_run_hook()
Exemple #2
0
def _process_wrapper(return_queue: multiprocessing.Queue,
                     error_queue: multiprocessing.Queue,
                     logging_queue: multiprocessing.Queue, process_id: str,
                     extension_package_import_paths: Sequence[str],
                     call_spec: CallSpec) -> None:
    """Executes the provided function in a parallel process."""
    gdm_logger.initialize_child_process_logging(logging_queue)
    short_description = f"{call_spec.function.__name__} in process {os.getpid()}"
    logger = gdm_logger.get_logger()
    logger.debug(f"{short_description}: starting execution of {call_spec}...")
    # The state of the main process (such as registered extension packages) is not
    # copied over when using "forkserver" or "spawn" as the process start method.
    for import_path in extension_package_import_paths:
        try:
            package_registrar.register(importlib.import_module(import_path))
        except (ImportError, errors.PackageRegistrationError) as e:
            logger.debug(
                f"{short_description}: failed to import and register GDM "
                f"extension package with import path {import_path}. "
                f"Error: {e!r}. Proceeding despite the failure.")

    manager_inst = manager.Manager()
    try:
        return_value = call_spec.function(manager_inst, *call_spec.args,
                                          **call_spec.kwargs)
        logger.debug(f"{short_description}: execution succeeded. "
                     f"Return value: {return_value}.")
        return_queue.put((process_id, return_value))
    except Exception as e:  # pylint: disable=broad-except
        logger.warning(
            f"{short_description}: execution raised an error: {e!r}.")
        error_queue.put((process_id, (type(e).__name__, str(e))))
    finally:
        manager_inst.close()
Exemple #3
0
    def stop(self):
        """Stops process if process is running.

    Raises:
        RuntimeError: if called when process is not currently running
        OSError: if a system related exception occurs.

    Note:
        When calling this method you should use is_started() to check if
        process was previously started to prevent raising an error.
    """
        if self.is_started():
            if self._process.is_alive():
                try:
                    self._terminate_event.set()
                except IOError:  # manager shutdown
                    pass
            try:
                stop_event_value = self._stop_event.wait(timeout=5)
                if not stop_event_value:
                    msg = ("Device {} failed to stop child process {}. "
                           "Stop event was not set.").format(
                               self.device_name, self.process_name)
                    gdm_logger.get_logger().error(msg)
                    raise IOError(msg)
            except (IOError, ValueError):  # manager shutdown failed
                pass
            self._process.join(timeout=1)
            if self._process.is_alive():
                self._process.terminate()
            delattr(self, "_process")
        else:
            msg = (
                "Device {} failed to stop child process {}. Child process is not "
                "currently running.").format(self.device_name,
                                             self.process_name)
            gdm_logger.get_logger().error(msg)
            raise RuntimeError(msg)
Exemple #4
0
These are settable properties, usually initialized as None. They allow users to
enable additional capabilities or set properties undetectable via device
communication. For example, power_switch_port to enable power cycling via a
powerswitch or an alias.

@decorators.OptionalProperty
def alias(self):
"""
import functools
import inspect
import logging
import time
from gazoo_device import errors
from gazoo_device import gdm_logger

logger_gdm = gdm_logger.get_logger()

# Enable specifying logger levels by decorators.<LEVEL> (so users don't have to import logging)
NONE = None
DEBUG = logging.DEBUG
INFO = logging.INFO
WARNING = logging.WARNING
ERROR = logging.ERROR
CRITICAL = logging.CRITICAL

MESSAGES = {
    "START":
    "{device_name} starting {class_name}.{method_name}",
    "SKIP":
    "{device_name} {class_name}.{method_name} skipped. {skip_reason}.",
    "SUCCESS":
# 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.

"""Default implementation of the PwRPC (Pigweed RPC) lighting capability."""
from typing import Any, Callable, Optional
from gazoo_device import decorators
from gazoo_device import errors
from gazoo_device import gdm_logger
from gazoo_device.capabilities.interfaces import pwrpc_light_base
from gazoo_device.protos import lighting_service_pb2
from gazoo_device.switchboard.transports import pigweed_rpc_transport
from gazoo_device.utility import pwrpc_utils

_LIGHTING_COLOR_PROTO_CLASS = "gazoo_device.protos.lighting_service_pb2.LightingColor"
logger = gdm_logger.get_logger()


class PwRPCLightDefault(pwrpc_light_base.PwRPCLightBase):
  """Pigweed RPC lighting capability for devices communicating over PwRPC."""

  def __init__(self,
               device_name: str,
               switchboard_call: Callable[..., Any],
               rpc_timeout_s: int):
    """Creates an instance of the PwRPCLightDefault capability.

    Args:
      device_name: Device name used for logging.
      switchboard_call: The switchboard.call method.
      rpc_timeout_s: Timeout (s) for RPC call.
Exemple #6
0
# 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.

"""Module for log parser."""
import codecs
import os
import time

from gazoo_device import errors
from gazoo_device import gdm_logger
from gazoo_device.switchboard import data_framer
from gazoo_device.switchboard import log_process

logger = gdm_logger.get_logger("log_parser")

DISPLAY_REFRESH = 3.0  # secs


class LogParser(object):
  """Provides ability to search for specific events in log file."""

  def __init__(self, parser_obj, log_path, display_refresh=DISPLAY_REFRESH):
    """Initialize LogParser class using provided information.

    Args:
        parser_obj (Parser): Instance of class Parser
        log_path (str): Path to log filename containing raw, log event data
        display_refresh (float): Number of seconds to wait prior to refresh
          of display
Exemple #7
0
NOTE: the WebSocket protocol is NOT the same thing as a TCP/IP socket.
The WebSocket protocol is an application layer (layer 7) protocol.
    See https://tools.ietf.org/html/rfc6455.
TCP socket is a transport layer (layer 4) protocol.
    For a transport based on a TCP socket, see tcp_transport.py.
"""
import traceback

from gazoo_device import gdm_logger
from gazoo_device.switchboard import transport_properties
from gazoo_device.switchboard.transports import tcp_transport
from gazoo_device.switchboard.transports import transport_base
import websocket

logger = gdm_logger.get_logger(__file__)


class WebSocketTransport(transport_base.TransportBase):
  """WebSocket-based transport."""

  def __init__(self,
               comms_address,
               connect_timeout=tcp_transport.CONNECT_TIMEOUT,
               auto_reopen=False,
               open_on_start=True):
    """Initialize the WebSocketTransport.

    Args:
        comms_address (str): websocket URL to connect to (ws://...)
        connect_timeout (float): timeout on the socket instance before
Exemple #8
0
def target(logging_queue):
    gdm_logger.initialize_child_process_logging(logging_queue)
    logger = gdm_logger.get_logger()
    logger.info("I'm a child process with PID {}".format(os.getpid()))
Exemple #9
0
import logging
import os
from typing import Any, Dict, List, Sequence

from gazoo_device import custom_types
from gazoo_device import errors
from gazoo_device import gdm_logger
from gazoo_device import manager

# Device properties for gazoo device analytics.
_DEVICE_PROPS = ("name", "device_type", "model", "platform", "serial_number",
                 "wifi_mac_address", "firmware_version", "firmware_branch",
                 "firmware_type", "alias", "communication_address",
                 "secondary_communication_address", "build_date",
                 "initial_code_name")
_LOGGER = gdm_logger.get_logger()
_MANAGER_INSTANCE = None


def _set_auxiliary_props(properties: Dict[str, Any], device_name: str):
    """Sets props on device instance to the values in the config.

  Label is translated to Alias and dimensions are left out.

  Args:
    properties: Dictionary of device properties and their values.
    device_name: Id of the device instance.
  """
    for prop_name, value in properties.items():
        if prop_name in ["id", "dimensions"]:
            continue