Example #1
0
 def test_pass_ip_address(self, mock_popen):
     self.stdout_mock.write(
         dedent("""
             10.192.202.23\toctopi.local
             """).encode("utf-8"))
     self.stdout_mock.seek(0)
     mock_popen.return_value.stdout = self.stdout_mock
     self.stderr_mock.seek(0)
     mock_popen.return_value.stderr = self.stderr_mock
     get_avahi_hostname("10.192.202.23")
     mock_popen.assert_called_with(
         ["avahi-resolve-address", "10.192.202.23"], stdout=-1, stderr=-1)
Example #2
0
 def test_err(self, mock_popen, mock_logger):
     self.stderr_mock.write(
         dedent("""
             Failed to create client object: Daemon not running
             """).encode("utf-8"))
     self.stdout_mock.seek(0)
     mock_popen.return_value.stdout = self.stdout_mock
     self.stderr_mock.seek(0)
     mock_popen.return_value.stderr = self.stderr_mock
     get_avahi_hostname("10.192.202.23")
     self.assertTrue(mock_logger.call_count, 1)
     mock_logger.called_with(
         "avahi-resolve-address error: Failed to create client object: Daemon not running"
     )
Example #3
0
def check_printers():
    app.logger.debug("Checking known printers...")
    for raw_printer in printers.get_printers():
        printer = clients.get_printer_instance(raw_printer)
        if printer.hostname is not None:
            current_ip = network.get_avahi_address(printer.hostname)
            if current_ip is not None and current_ip != printer.ip:
                printer.ip = current_ip
                printer.update_network_host()
        else:
            hostname = network.get_avahi_hostname(printer.ip)
            if hostname is not None:
                printer.hostname = hostname
                printer.update_network_host()
        printer.is_alive()
        printers.update_printer(
            uuid=printer.uuid,
            name=printer.name,
            hostname=printer.hostname,
            ip=printer.ip,
            port=printer.port,
            protocol=printer.protocol,
            client=printer.client_name(),
            client_props={
                "version": printer.client_info.version,
                "connected": printer.client_info.connected,
                "access_level": printer.client_info.access_level,
                "api_key": printer.client_info.api_key,
                "webcam": printer.webcam(),
            },
            printer_props=printer.get_printer_props(),
        )
Example #4
0
def scan_network():
    app.logger.info("Scanning network for printers...")
    for line in do_arp_scan(settings.get_val("network_interface")):
        (ip, _) = line
        hostname = get_avahi_hostname(ip)
        # it's communicating, let's sniff it for a printer
        sniff_printer.delay(hostname, ip)
Example #5
0
def printer_create():
    data = request.json
    if not data:
        return abort(400)
    ip = data.get("ip", None)
    name = data.get("name", None)
    if (not ip or not name or re.match(
            r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:?\d{0,5}$", ip) is None):
        return abort(400)
    if printers.get_printer(ip) is not None:
        return abort(409)
    hostname = network.get_avahi_hostname(ip)
    printer = drivers.get_printer_instance({
        "hostname": hostname,
        "ip": ip,
        "name": name,
        "client": "octoprint",  # TODO make this more generic
    })
    printer.sniff()
    network_devices.upsert_network_device(ip=ip,
                                          retry_after=None,
                                          disabled=False)
    printers.add_printer(
        name=name,
        hostname=hostname,
        ip=ip,
        client=printer.client_name(),
        client_props={
            "version": printer.client.version,
            "connected": printer.client.connected,
            "read_only": printer.client.read_only,
        },
    )
    return "", 201
Example #6
0
def discover_printers():
    if not settings.get_val("network_discovery"):
        return
    app.logger.debug("Discovering network printers...")
    now = datetime.utcnow()
    to_deactivate = printers.get_printers()
    to_skip_ip = [
        device["ip"] for device in network_devices.get_network_devices()
        if (device["retry_after"] and device["retry_after"] > now)
        or device["disabled"]
    ]
    for line in do_arp_scan(settings.get_val("network_interface")):
        (ip, _) = line
        to_deactivate = [
            printer for printer in to_deactivate if printer["ip"] != ip
        ]
        if ip in to_skip_ip:
            continue
        hostname = get_avahi_hostname(ip)
        # it's communicating, let's sniff it for a printer
        sniff_printer.delay(hostname, ip)

    for printer in to_deactivate:
        app.logger.debug(
            "%s (%s) was not encountered on the network, deactivating" %
            (printer["hostname"], printer["ip"]))
        printer["client_props"]["connected"] = False
        printers.update_printer(**printer)
Example #7
0
def scan_network(org_uuid, network_interface="wlan0"):
    app.logger.info("Scanning network %s for printers..." % network_interface)
    for line in do_arp_scan(network_interface):
        (ip, _) = line
        hostname = get_avahi_hostname(ip)
        # it's communicating, let's sniff it for a printer
        sniff_printer.delay(org_uuid, hostname, ip)
Example #8
0
    def test_drop_error_message(self, mock_popen):
        self.stdout_mock.write(
            b"""
Failed to resolve address '10.192.202.200': Timeout reached
"""
        )
        self.stdout_mock.seek(0)
        mock_popen.return_value.stdout = self.stdout_mock
        self.assertEqual(get_avahi_hostname("10.192.202.200"), None)
Example #9
0
    def test_regex(self, mock_popen):
        self.stdout_mock.write(
            b"""
10.192.202.23\toctopi.local
"""
        )
        self.stdout_mock.seek(0)
        mock_popen.return_value.stdout = self.stdout_mock
        result = get_avahi_hostname("10.192.202.23")
        self.assertEqual(result, "octopi.local")
Example #10
0
 def test_regex(self, mock_popen):
     self.stdout_mock.write(
         dedent("""
             10.192.202.23\toctopi
             """).encode("utf-8"))
     self.stdout_mock.seek(0)
     mock_popen.return_value.stdout = self.stdout_mock
     self.stderr_mock.seek(0)
     mock_popen.return_value.stderr = self.stderr_mock
     result = get_avahi_hostname("10.192.202.23")
     self.assertEqual(result, "octopi.local")
Example #11
0
def check_printer(printer_uuid):
    app.logger.debug("Checking printer %s" % printer_uuid)
    raw_printer = printers.get_printer(printer_uuid)
    # todo: The `get_printer` method should raise an exception instead of returning None
    if raw_printer is None:
        app.logger.info(
            "Printer was deleted after it was scheduled for update.")
        return
    raw_client = network_clients.get_network_client(
        raw_printer["network_client_uuid"])
    printer_data = dict(raw_client)
    printer_data.update(raw_printer)
    printer = clients.get_printer_instance(printer_data)
    # websocket printers are not expected to change
    if printer.protocol in ["http", "https"]:
        if printer.hostname is not None:
            current_ip = network.get_avahi_address(printer.hostname)
            if current_ip is not None and current_ip != printer.ip:
                printer.ip = current_ip
                printer.update_network_base()
        hostname = network.get_avahi_hostname(printer.ip)
        if hostname is not None and hostname != printer.hostname:
            printer.hostname = hostname
            printer.update_network_base()
    now = datetime.now()
    if now.minute % 15 == 0 and printer.client_info.connected:
        printer.sniff()
        printer.karmen_sniff()
    else:
        printer.is_alive()

    if (printer.client_info.pill_info and printer.client_info.pill_info.get(
            "update_status", None) is not None):
        printer.karmen_sniff()

    if printer.hostname != raw_client.get(
            "hostname") or printer.ip != raw_client.get("ip"):
        network_clients.update_network_client(
            uuid=raw_client["uuid"],
            hostname=printer.hostname,
            ip=printer.ip,
        )
    printers.update_printer(
        uuid=printer.uuid,
        client_props={
            "version": printer.client_info.version,
            "connected": printer.client_info.connected,
            "access_level": printer.client_info.access_level,
            "api_key": printer.client_info.api_key,
            "webcam": printer.client_info.webcam,
            "plugins": printer.client_info.plugins,
            "pill_info": printer.client_info.pill_info,
        },
    )
Example #12
0
def check_printer(printer_uuid):
    app.logger.debug("Checking printer %s" % printer_uuid)
    raw_printer = printers.get_printer(printer_uuid)
    raw_client = network_clients.get_network_client(
        raw_printer["network_client_uuid"])
    printer_data = dict(raw_client)
    printer_data.update(raw_printer)
    printer = clients.get_printer_instance(printer_data)
    # websocket printers are not expected to change
    if printer.protocol in ["http", "https"]:
        if printer.hostname is not None:
            current_ip = network.get_avahi_address(printer.hostname)
            if current_ip is not None and current_ip != printer.ip:
                printer.ip = current_ip
                printer.update_network_base()
        hostname = network.get_avahi_hostname(printer.ip)
        if hostname is not None and hostname != printer.hostname:
            printer.hostname = hostname
            printer.update_network_base()
    now = datetime.now()
    if now.minute % 15 == 0 and printer.client_info.connected:
        printer.sniff()
    else:
        printer.is_alive()

    if printer.hostname != raw_client.get(
            "hostname") or printer.ip != raw_client.get("ip"):
        network_clients.update_network_client(
            uuid=raw_client["uuid"],
            hostname=printer.hostname,
            ip=printer.ip,
        )

    printers.update_printer(
        uuid=printer.uuid,
        client_props={
            "version": printer.client_info.version,
            "connected": printer.client_info.connected,
            "access_level": printer.client_info.access_level,
            "api_key": printer.client_info.api_key,
            "webcam": printer.client_info.webcam,
            "plugins": printer.client_info.plugins,
        },
    )
Example #13
0
def printer_create(org_uuid):
    data = request.json
    if not data:
        return abort(make_response(jsonify(message="Missing payload"), 400))
    uuid = guid.uuid4()
    ip = data.get("ip", None)
    port = data.get("port", None)
    hostname = data.get("hostname", None)
    name = data.get("name", None)
    api_key = data.get("api_key", None)
    protocol = data.get("protocol", "http")
    path = data.get("path", "")
    token = data.get("token", None)

    if token is not None and token != "":
        if not app.config.get("CLOUD_MODE"):
            return abort(make_response(jsonify(message="Missing token"), 400))
        existing_network_client = network_clients.get_network_client_by_socket_token(
            token)
        if existing_network_client:
            existing_printer = printers.get_printer_by_network_client_uuid(
                org_uuid, existing_network_client.get("uuid"))
            if existing_printer is not None:
                return abort(
                    make_response(jsonify(message="Printer exists"), 409))
        path = ""
        hostname = ""
        ip = ""
        protocol = ""
        port = 0
    else:
        if app.config.get("CLOUD_MODE"):
            return abort(
                make_response(
                    jsonify(
                        message=
                        "Cannot add printer without a token in CLOUD_MODE"),
                    500,
                ))
        if ((not ip and not hostname) or not name
                or protocol not in ["http", "https"]
                or (hostname
                    and re.match(r"^[0-9a-zA-Z.-]+\.local$", hostname) is None)
                or
            (ip
             and re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", ip) is None)
                or (port and re.match(r"^\d{0,5}$", str(port)) is None)):
            return abort(
                make_response(
                    jsonify(
                        message="Missing some network data about the printer"),
                    400))

        if hostname and not ip:
            ip = network.get_avahi_address(hostname)
            if not ip:
                return abort(
                    make_response(
                        jsonify(message="Cannot resolve %s with mDNS" %
                                hostname), 500))
        if ip and not hostname:
            hostname = network.get_avahi_hostname(ip)

        existing_network_client = network_clients.get_network_client_by_props(
            hostname, ip, port, path)
        if existing_network_client:
            existing_printer = printers.get_printer_by_network_client_uuid(
                org_uuid, existing_network_client.get("uuid"))
            if existing_printer is not None:
                return abort(
                    make_response(jsonify(message="Printer exists"), 409))

    if not existing_network_client:
        existing_network_client = {
            "uuid": guid.uuid4(),
            "hostname": hostname,
            "client": "octoprint",  # TODO make this more generic
            "protocol": protocol,
            "ip": ip,
            "port": port,
            "path": path,
            "token": token,
        }
        network_clients.add_network_client(**existing_network_client)

    printer = clients.get_printer_instance({
        "uuid":
        uuid,
        "network_client_uuid":
        existing_network_client["uuid"],
        "organization_uuid":
        org_uuid,
        "name":
        name,
        "client":
        existing_network_client["client"],
        "protocol":
        existing_network_client["protocol"],
        "hostname":
        existing_network_client["hostname"],
        "ip":
        existing_network_client["ip"],
        "port":
        existing_network_client["port"],
        "path":
        existing_network_client["path"],
        "token":
        existing_network_client["token"],
    })
    printer.add_api_key(api_key)
    printer.update_network_base()
    printer.sniff()
    printers.add_printer(
        uuid=uuid,
        network_client_uuid=existing_network_client["uuid"],
        organization_uuid=org_uuid,
        name=name,
        client=printer.client_name(),
        client_props={
            "version": printer.client_info.version,
            "connected": printer.client_info.connected,
            "access_level": printer.client_info.access_level,
            "api_key": printer.client_info.api_key,
            "webcam": printer.client_info.webcam,
            "plugins": printer.client_info.plugins,
        },
    )
    # TODO cache webcam, job, status for a small amount of time in this client
    return jsonify(make_printer_response(printer,
                                         ["status", "webcam", "job"])), 201
Example #14
0
def printer_create():
    data = request.json
    if not data:
        return abort(make_response("", 400))
    uuid = uuidmodule.uuid4()
    ip = data.get("ip", None)
    port = data.get("port", None)
    hostname = data.get("hostname", None)
    name = data.get("name", None)
    api_key = data.get("api_key", None)
    protocol = data.get("protocol", "http")

    if ((not ip and not hostname) or not name
            or protocol not in ["http", "https"] or
        (hostname and re.match(r"^[0-9a-zA-Z.-]+\.local$", hostname) is None)
            or
        (ip and re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$", ip) is None)
            or (port and re.match(r"^\d{0,5}$", str(port)) is None)):
        return abort(make_response("", 400))

    if hostname and not ip:
        ip = network.get_avahi_address(hostname)
        if not ip:
            return abort(
                make_response("Cannot resolve %s with mDNS" % hostname, 500))
    if ip and not hostname:
        hostname = network.get_avahi_hostname(ip)

    if printers.get_printer_by_network_props(hostname, ip, port) is not None:
        return abort(make_response("", 409))

    printer = clients.get_printer_instance({
        "uuid": uuid,
        "hostname": hostname,
        "ip": ip,
        "port": port,
        "name": name,
        "protocol": protocol,
        "client": "octoprint",  # TODO make this more generic
    })
    printer.add_api_key(api_key)
    printer.sniff()
    printers.add_printer(
        uuid=uuid,
        name=name,
        hostname=hostname,
        ip=ip,
        port=port,
        protocol=printer.protocol,
        client=printer.client_name(),
        client_props={
            "version": printer.client_info.version,
            "connected": printer.client_info.connected,
            "access_level": printer.client_info.access_level,
            "api_key": printer.client_info.api_key,
            "webcam": printer.webcam(),
        },
    )
    # TODO cache webcam, job, status for a small amount of time in client
    return jsonify(make_printer_response(printer,
                                         ["status", "webcam", "job"])), 201