Exemple #1
0
def test_retrieving_settings():
    """Test that the correct settings are retrieved."""
    test_config = get_config(override_default="test")
    dev_config = get_config(override_default="dev")
    prod_config = get_config(override_default="prod")
    wrong_config = get_config(override_default="wrong")

    assert test_config == TestConfig
    assert dev_config == DevConfig
    assert prod_config == ProdConfig
    assert wrong_config == DevConfig
Exemple #2
0
def set_wpa_mode():
    """Perform the setup and intialization work for interfaces with no ap present."""

    logger.debug("setting all wlan into wpa mode")
    session = get_session()

    # get the info for the wpa_supplicant file
    wifi_defs = session.query(Wifi).filter(Wifi.mode != "ap").all()
    networks = []
    for wifi in wifi_defs:
        new_network = {}
        new_network["ssid"] = wifi.name
        new_network["password"] = wifi.password
        networks.append(new_network)

    iptables_file(None, None, flush_only=True)
    interface_file()
    wpa_supplicant_file(networks)
    dhcpcd_file()

    config = get_config()
    path = config.APP_DIR + "/network/wpa_script.sh"

    command = ["sudo", "sh", path]
    subprocess.check_call(command)
    session.close()
Exemple #3
0
def check_rabbitmq_address(logger, address):
    """Check if the address is good, by trying to connect."""

    config = get_config()
    user = config.RABBITMQ_USER
    password = config.RABBITMQ_PASSWORD
    port = 5672
    virtual_host = config.RABBITMQ_VHOST

    credentials = pika.PlainCredentials(username=user, password=password)
    parameters = pika.ConnectionParameters(host=address,
                                           port=port,
                                           virtual_host=virtual_host,
                                           credentials=credentials)

    try:
        logger.debug(f"testing connection to: {address}")
        connection = pika.BlockingConnection(parameters=parameters)
        if connection.is_open:
            logger.debug(f"Connection to {address} is good.")
            connection.close()
            return True
    except AMQPConnectionError:
        logger.debug(f"Connection to {address} failed.")
        return False

    return False
Exemple #4
0
def create_revision(message):
    """Create a database migration using alembic."""

    config = get_config()
    alembic_cnf = AlConfig(config.PROJECT_ROOT + "/migrations/alembic.ini")
    alembic_cnf.set_main_option("script_location",
                                config.PROJECT_ROOT + "/migrations")

    al_command.revision(alembic_cnf, message=message, autogenerate=True)
Exemple #5
0
def database_upgrade(revision):
    """Upgrade database to given revision."""

    config = get_config()
    alembic_cnf = AlConfig(config.PROJECT_ROOT + "/migrations/alembic.ini")
    alembic_cnf.set_main_option("script_location",
                                config.PROJECT_ROOT + "/migrations")

    al_command.upgrade(alembic_cnf, revision)
Exemple #6
0
def set_ap_mode():
    """Perform the setup and intialization work for interfaces with an ap present."""

    logger.debug("setting wifi into ap mode")
    session = get_session()

    # get the wlan0 and wlan1 dhcp states
    try:
        ap_interface = session.query(Interface).filter_by(state="ap").first()
        ap_ssid = ap_interface.credentials[0].name
        ap_password = ap_interface.credentials[0].password

    except NoResultFound:
        # error. abort
        logger.warning("No interface with state set to 'ap'. Aborting")
        return

    # get info for interface file
    if ap_interface.interface == "wlan0":
        wlan0_dhcp = False
        wlan1_dhcp = True

    else:
        wlan0_dhcp = True
        wlan1_dhcp = False

    # get the info for the wpa_supplicant file
    wifi_defs = session.query(Wifi).filter(Wifi.mode != "ap").all()
    networks = []
    for wifi in wifi_defs:
        new_network = {}
        new_network["ssid"] = wifi.name
        new_network["password"] = wifi.password
        networks.append(new_network)

    # get the information for the iptables_file
    internal_interface = ap_interface.interface
    external_interface = get_external_interface()

    iptables_file(external_interface, internal_interface)
    interface_file(wlan0_dhcp=wlan0_dhcp, wlan1_dhcp=wlan1_dhcp)
    wpa_supplicant_file(networks)
    dhcpcd_file(interface=ap_interface.interface)
    dnsmasq_file(interface=ap_interface.interface)
    hostapd_file(ap_interface.interface, ap_ssid, ap_password)

    config = get_config()

    path = config.APP_DIR + "/network/ap_script.sh"

    command = ["sudo", "sh", path, ap_interface.interface]
    subprocess.check_call(command)

    session.close()
Exemple #7
0
def search_on_socket(logger, session, connection):
    """Look for farm monitor presence notifier on the network."""

    config = get_config()
    presence_port = config.PRESENCE_PORT

    # get the first interface that is for farm monitor
    interface = session.query(
        Interface.interface).filter_by(is_for_fm=True).scalar()

    if interface is None:
        logger.warning(
            "Interface from database is None. Has initial configuration been run? Setting interface to 'eth0'"
        )
        interface = "eth0"

    interface_address = get_ip_of_interface(interface, broadcast=True)

    logger.info(f"looking for FarmMonitor address on interface {interface}")
    logger.debug(f"address is {interface_address}:{presence_port}")

    # Create UDP socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)

    # Ask operating system to let us do broadcasts from socket
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)

    # Bind UDP socket to local port so we can receive pings
    sock.bind((interface_address, int(presence_port)))

    try:
        while True:
            timeout = 5
            ready = select.select([sock], [], [], timeout)
            # Someone answered our ping
            if ready[0]:
                _, addrinfo = sock.recvfrom(2)
                if check_rabbitmq_address(logger, addrinfo[0]):
                    sock.close()
                    logger.debug(
                        f"Found FarmMonitor at {addrinfo[0]}:{addrinfo[1]}")
                    connection.address = addrinfo[0]
                    session.commit()
                    return True
                logger.debug(
                    f"Reply from {addrinfo[0]}:{addrinfo[1]}, but no rabbitmq server present"
                )
            else:
                logger.debug("No broadcast from FarmMonitor yet")

    except KeyboardInterrupt:
        sock.close()
        session.commit()
        return False
Exemple #8
0
def create_tables():
    """Create all database tables for first time setup."""
    click.echo("creating all tables")

    create_all_tables()

    config = get_config()
    alembic_cnf = AlConfig(config.PROJECT_ROOT + "/migrations/alembic.ini")
    alembic_cnf.set_main_option("script_location",
                                config.PROJECT_ROOT + "/migrations")
    click.echo("stamping alembic head")
    al_command.stamp(alembic_cnf, "head")
    click.echo("done")
Exemple #9
0
def get_rabbitmq_address(logger, session):  # noqa: C901
    """Find and return the address of the RabbitMQ server to connect to."""

    try:
        connection = session.query(Connection).one()
    except NoResultFound:
        connection = Connection()
        session.add(connection)

    # try environment variable address (if present) to see if it works.
    config = get_config()
    if config.RABBITMQ_HOST_ADDRESS is not None:
        logger.debug(
            f"trying environment variable for rabbitmq address of {config.RABBITMQ_HOST_ADDRESS}"
        )
        if check_rabbitmq_address(logger, config.RABBITMQ_HOST_ADDRESS):
            logger.info(
                f"environment variable address of host {config.RABBITMQ_HOST_ADDRESS} was found and the url was valid"
            )
            connection.address = config.RABBITMQ_HOST_ADDRESS
            session.commit()
            return True

    # try previously found address (if available) to see if it is still working
    if connection.address:
        logger.debug(
            f"trying previous rabbitmq address of {connection.address}")
        if check_rabbitmq_address(logger, connection.address):
            logger.info("previously used rabbitmq address is still valid")
            return True

    possible_addresses = ["fm_rabbitmq", "host.docker.internal", "localhost"]

    for address in possible_addresses:
        logger.debug(f"testing address: {address}")
        try:
            address = socket.gethostbyname(address)
            if check_rabbitmq_address(logger, address):
                logger.info(
                    f"'{address}' host was found and the url was valid")
                connection.address = address
                session.commit()
                return True

        except socket.gaierror:
            logger.debug(f"'{address}' host was not found")

    # if all else fails, look for farm monitor presence notifier
    return search_on_socket(logger, session, connection)
Exemple #10
0
    def __init__(self, logger):
        """Create the Connection object."""

        self.LOGGER = logger

        # store and manage internal state
        self._connection = None
        self._channel = None
        self._closing = False

        config = get_config()

        # connection parameters
        self._user = config.RABBITMQ_USER
        self._password = config.RABBITMQ_PASSWORD
        # self._host = host - this is set in the overwritten function
        self._port = 5672
        self._virtual_host = config.RABBITMQ_VHOST
Exemple #11
0
"""Main celery module."""
import logging
import time

import schedule
from amqp import exceptions as amqp_exceptions  # type: ignore
from celery import Celery, exceptions
from celery.result import AsyncResult

from fd_device.device.update import get_device_info
from fd_device.grainbin.update import get_grainbin_updates
from fd_device.settings import get_config

LOGGER = logging.getLogger("fd.celery_runner")
CONFIG = get_config()

app = Celery()
app.config_from_object("fd_device.settings:CeleryConfig")


def send_update_to_server(task_name: str, payload, ignore_result: bool = False):
    """Send a payload to a specific task on the server."""

    try:
        LOGGER.debug(f"Sending '{task_name}' to Celery broker")
        result: AsyncResult = app.send_task(
            task_name, args=[payload], ignore_result=ignore_result
        )
        if not ignore_result:
            response = result.get(timeout=CONFIG.SEND_TASK_GET_TIMEOUT)
            LOGGER.debug(f"'{task_name}' task returned: {response}")
Exemple #12
0
# -*- coding: utf-8 -*-
"""Click commands."""
import os
import sys
from glob import glob
from subprocess import PIPE, call, run
from typing import List

import click
from pyment import PyComment

from fd_device.settings import get_config

config = get_config()  # pylint: disable=invalid-name
APP_DIR = config.APP_DIR
PROJECT_ROOT = config.PROJECT_ROOT
TEST_PATH = os.path.join(PROJECT_ROOT, "tests")
MAX_DEPTH_RECUR = 50
"""The maximum depth to reach while recursively exploring sub folders."""


def get_files_from_dir(path, recursive=True, depth=0, file_ext=".py"):
    """Retrieve the list of files from a folder.

    @param path: file or directory where to search files
    @param recursive: if True will search also sub-directories
    @param depth: if explore recursively, the depth of sub directories to follow
    @param file_ext: the files extension to get. Default is '.py'
    @return: the file list retrieved. if the input is a file then a one element list.
    """
    file_list = []
Exemple #13
0
from __future__ import with_statement
from alembic import context
from sqlalchemy import engine_from_config, pool
from logging.config import fileConfig

# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config

# this will overwrite the ini-file sqlalchemy.url path
# with the path given in the config of the main code
from fd_device.settings import get_config
device_config = get_config()
config.set_main_option('sqlalchemy.url', device_config.SQLALCHEMY_DATABASE_URI)
config.set_main_option('script_location', device_config.PROJECT_ROOT + '/migrations')

# Interpret the config file for Python logging.
# This line sets up loggers basically.
fileConfig(config.config_file_name)

# add your model's MetaData object here
# for 'autogenerate' support
from fd_device.database.base import get_base
from fd_device.database.device import Device, Grainbin
from fd_device.database.system import Hardware
Base = get_base()
target_metadata = Base.metadata

# other values from the config, defined by the needs of env.py,
# can be acquired:
# my_important_option = config.get_main_option("my_important_option")
Exemple #14
0
def test_main_env():
    """Test that the main environment variable is set for testing."""

    config = get_config()
    assert config == TestConfig