← Back to team overview

sts-sponsors team mailing list archive

[Merge] ~ack/maas:drop-maas-rack-send-beacons into maas:master

 

Alberto Donato has proposed merging ~ack/maas:drop-maas-rack-send-beacons into maas:master.

Commit message:
drop unused "maas-rack send-beacon" option, which was only meant for testing



Requested reviews:
  MAAS Maintainers (maas-maintainers)

For more details, see:
https://code.launchpad.net/~ack/maas/+git/maas/+merge/437345
-- 
Your team MAAS Maintainers is requested to review the proposed merge of ~ack/maas:drop-maas-rack-send-beacons into maas:master.
diff --git a/src/provisioningserver/__main__.py b/src/provisioningserver/__main__.py
index 5f22393..7550036 100644
--- a/src/provisioningserver/__main__.py
+++ b/src/provisioningserver/__main__.py
@@ -20,14 +20,12 @@ import provisioningserver.utils.beaconing
 import provisioningserver.utils.dhcp
 import provisioningserver.utils.scan_network
 from provisioningserver.utils.script import MainScript
-import provisioningserver.utils.send_beacons
 
 COMMON_COMMANDS = {
     "observe-arp": provisioningserver.utils.arp,
     "observe-beacons": provisioningserver.utils.beaconing,
     "observe-mdns": provisioningserver.utils.avahi,
     "observe-dhcp": provisioningserver.utils.dhcp,
-    "send-beacons": provisioningserver.utils.send_beacons,
     "scan-network": provisioningserver.utils.scan_network,
     "setup-dns": provisioningserver.dns.commands.setup_dns,
     "get-named-conf": provisioningserver.dns.commands.get_named_conf,
diff --git a/src/provisioningserver/utils/send_beacons.py b/src/provisioningserver/utils/send_beacons.py
deleted file mode 100644
index 07bf0f0..0000000
--- a/src/provisioningserver/utils/send_beacons.py
+++ /dev/null
@@ -1,143 +0,0 @@
-# Copyright 2017 Canonical Ltd.  This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Utilities for sending and receiving beacons on attached networks."""
-
-
-from pprint import pformat
-import sys
-from textwrap import dedent
-
-from provisioningserver import logger
-from provisioningserver.logger import DEFAULT_LOG_VERBOSITY, LegacyLogger
-from provisioningserver.utils.beaconing import (
-    BEACON_IPV4_MULTICAST,
-    BEACON_PORT,
-    create_beacon_payload,
-)
-from provisioningserver.utils.network import (
-    get_all_interfaces_definition,
-    get_ifname_ifdata_for_destination,
-)
-from provisioningserver.utils.services import (
-    BeaconingSocketProtocol,
-    interface_info_to_beacon_remote_payload,
-)
-
-log = LegacyLogger()
-
-
-def add_arguments(parser):
-    """Add this command's options to the `ArgumentParser`.
-
-    Specified by the `ActionScript` interface.
-    """
-    parser.description = dedent(
-        """\
-        Send solicitation beacons to a particular address.
-        """
-    )
-    parser.add_argument(
-        "-v",
-        "--verbose",
-        action="store_true",
-        required=False,
-        help="Verbose packet output.",
-    )
-    parser.add_argument(
-        "-s",
-        "--source",
-        type=str,
-        required=False,
-        help="Source address to send beacons from.",
-    )
-    parser.add_argument(
-        "-t",
-        "--timeout",
-        type=int,
-        required=False,
-        default=5,
-        help="Number of seconds to wait for beacons.",
-    )
-    parser.add_argument(
-        "-p",
-        "--port",
-        type=int,
-        required=False,
-        default=0,
-        help="Port to listen for beacons on. By default, listens on a random "
-        "port.",
-    )
-    parser.add_argument(
-        "destination",
-        type=str,
-        nargs="?",
-        help="Destination to send beacon to. If not specified, will use the "
-        "MAAS multicast group (224.0.0.118 or ff02::15a) on all "
-        "interfaces.",
-    )
-
-
-def do_beaconing(args, interfaces=None, reactor=None):
-    """Sends out beacons based on the given arguments, and waits for replies.
-
-    :param args: The command-line arguments.
-    :param interfaces: The interfaces to send out beacons on.
-        Must be the result of `get_all_interfaces_definition()`.
-    """
-    if reactor is None:
-        from twisted.internet import reactor
-    if args.source is None:
-        source_ip = "::"
-    else:
-        source_ip = args.source
-    protocol = BeaconingSocketProtocol(
-        reactor,
-        process_incoming=True,
-        debug=True,
-        interface=source_ip,
-        port=args.port,
-        interfaces=interfaces,
-    )
-    if args.destination is None:
-        destination_ip = "::ffff:" + BEACON_IPV4_MULTICAST
-    elif ":" not in args.destination:
-        destination_ip = "::ffff:" + args.destination
-    else:
-        destination_ip = args.destination
-    if "224.0.0.118" in destination_ip:
-        protocol.send_multicast_beacons(interfaces, verbose=args.verbose)
-    else:
-        log.msg("Sending unicast beacon to '%s'..." % destination_ip)
-        ifname, ifdata = get_ifname_ifdata_for_destination(
-            destination_ip, interfaces
-        )
-        remote = interface_info_to_beacon_remote_payload(ifname, ifdata)
-        payload = {"remote": remote}
-        beacon = create_beacon_payload("solicitation", payload=payload)
-        protocol.send_beacon(beacon, (destination_ip, BEACON_PORT))
-    reactor.callLater(args.timeout, lambda: reactor.stop())
-    reactor.run()
-    return protocol
-
-
-def run(args, stdout=sys.stdout):
-    """Sends out beacons, waits for replies, and optionally print debug info.
-
-    :param args: Parsed output of the arguments added in `add_arguments()`.
-    :param stdout: Standard output stream to write to.
-    """
-    # Record the current time so we can figure out how long it took us to
-    # do all this scanning.
-    logger.configure(DEFAULT_LOG_VERBOSITY, logger.LoggingMode.COMMAND)
-    interfaces = get_all_interfaces_definition(annotate_with_monitored=False)
-    if args.verbose:
-        print("Interface dictionary:\n%s" % pformat(interfaces), file=stdout)
-    protocol = do_beaconing(args, interfaces=interfaces)
-    if args.verbose:
-        print("Transmit queue:\n%s" % pformat(protocol.tx_queue), file=stdout)
-        print("Receive queue:\n%s" % pformat(protocol.rx_queue), file=stdout)
-        print(
-            "Topology hints:\n%s" % pformat(protocol.topology_hints),
-            file=stdout,
-        )
diff --git a/src/provisioningserver/utils/tests/test_send_beacons.py b/src/provisioningserver/utils/tests/test_send_beacons.py
deleted file mode 100644
index ee1d9ba..0000000
--- a/src/provisioningserver/utils/tests/test_send_beacons.py
+++ /dev/null
@@ -1,212 +0,0 @@
-# Copyright 2017 Canonical Ltd.  This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Tests for ``provisioningserver.utils.send_beacons``."""
-
-
-from argparse import ArgumentParser
-import io
-from unittest.mock import ANY, Mock
-
-from testtools.matchers import MatchesStructure
-from twisted import internet
-from twisted.internet.task import Clock
-
-from maastesting.factory import factory
-from maastesting.matchers import Matches, MockCalledOnceWith, MockNotCalled
-from maastesting.testcase import MAASTestCase
-from provisioningserver.tests.test_security import SharedSecretTestCase
-from provisioningserver.utils import send_beacons as send_beacons_module
-from provisioningserver.utils.env import MAAS_SECRET
-from provisioningserver.utils.send_beacons import add_arguments, run
-
-
-def ArgumentsMatching(**kwargs):
-    """Tests if the output from `argparse` matches our expectations."""
-    return Matches(MatchesStructure.byEquality(**kwargs))
-
-
-TEST_INTERFACES = {
-    "eth0": {"links": []},
-    "eth1": {"links": [{"address": "192.168.0.1/24"}]},
-    "eth2": {
-        "links": [
-            {"address": "192.168.2.1/24"},
-            {"address": "192.168.3.1/24"},
-            {"address": "2001:db8::1/64"},
-        ]
-    },
-}
-
-
-class SendBeaconsTestCase(MAASTestCase):
-    def setUp(self):
-        super().setUp()
-        self.output = io.StringIO()
-        self.error_output = io.StringIO()
-        self.all_interfaces_mock = self.patch(
-            send_beacons_module, "get_all_interfaces_definition"
-        )
-        # Prevent logging from being reconfigured inside the test suite.
-        self.logger_mock = self.patch(send_beacons_module, "logger")
-        self.all_interfaces_mock.return_value = TEST_INTERFACES
-        self.parser = ArgumentParser()
-        add_arguments(self.parser)
-
-    def run_command(self, *args):
-        parsed_args = self.parser.parse_args([*args])
-        return run(parsed_args, stdout=self.output)
-
-
-class TestSendBeaconsCommand(SendBeaconsTestCase):
-    def setUp(self):
-        super().setUp()
-        self.send_beacons_mock = self.patch(send_beacons_module.do_beaconing)
-
-    def test_default_arguments(self):
-        self.run_command()
-        self.assertThat(
-            self.send_beacons_mock,
-            MockCalledOnceWith(
-                ArgumentsMatching(
-                    source=None, destination=None, timeout=5, port=0
-                ),
-                interfaces=TEST_INTERFACES,
-            ),
-        )
-
-    def test_interprets_long_arguments(self):
-        self.run_command(
-            "--verbose",
-            "--source",
-            "1.1.1.1",
-            "--timeout",
-            "42",
-            "--port",
-            "4242",
-            "2.2.2.2",
-        )
-        self.assertThat(
-            self.send_beacons_mock,
-            MockCalledOnceWith(
-                ArgumentsMatching(
-                    source="1.1.1.1",
-                    destination="2.2.2.2",
-                    timeout=42,
-                    port=4242,
-                ),
-                interfaces=TEST_INTERFACES,
-            ),
-        )
-
-    def test_interprets_short_arguments(self):
-        self.run_command(
-            "-v", "-s", "1.1.1.1", "-t", "42", "-p", "4242", "2.2.2.2"
-        )
-        self.assertThat(
-            self.send_beacons_mock,
-            MockCalledOnceWith(
-                ArgumentsMatching(
-                    source="1.1.1.1",
-                    destination="2.2.2.2",
-                    timeout=42,
-                    port=4242,
-                ),
-                interfaces=TEST_INTERFACES,
-            ),
-        )
-
-
-class FakeBeaconingSocketProtocol:
-    """Fake BeaconingSocketProtocol."""
-
-    tx_queue = []
-    rx_queue = []
-    topology_hints = []
-
-
-class TestSendBeaconsProtocolInteraction(
-    SendBeaconsTestCase, SharedSecretTestCase
-):
-    def setUp(self):
-        super().setUp()
-        MAAS_SECRET.set(factory.make_bytes())
-        self.protocol_mock = self.patch(
-            send_beacons_module, "BeaconingSocketProtocol"
-        )
-        self.fake_protocol = FakeBeaconingSocketProtocol()
-        self.protocol_mock.return_value = self.fake_protocol
-        self.fake_protocol.send_multicast_beacons = Mock()
-        self.fake_protocol.send_beacon = Mock()
-        # Prevent the command from starting and stopping the reactor.
-        self.reactor_mock = self.patch(internet, "reactor", Clock())
-        self.patch(self.reactor_mock, "run")
-
-    def test_sends_multicast_beacons_by_default(self):
-        self.run_command()
-        self.assertThat(
-            self.protocol_mock,
-            MockCalledOnceWith(
-                ANY,
-                debug=True,
-                interface="::",
-                port=0,
-                process_incoming=True,
-                interfaces=TEST_INTERFACES,
-            ),
-        )
-        self.assertThat(self.fake_protocol.send_beacon, MockNotCalled())
-        self.assertThat(
-            self.fake_protocol.send_multicast_beacons,
-            MockCalledOnceWith(TEST_INTERFACES, verbose=False),
-        )
-
-    def test_sends_multicast_beacons_with_verbose_flag(self):
-        self.run_command(
-            "--verbose",
-            "--source",
-            "1.1.1.1",
-            "--timeout",
-            "42",
-            "--port",
-            "4242",
-        )
-        self.assertThat(
-            self.protocol_mock,
-            MockCalledOnceWith(
-                ANY,
-                debug=True,
-                interface="1.1.1.1",
-                port=4242,
-                process_incoming=True,
-                interfaces=TEST_INTERFACES,
-            ),
-        )
-        self.assertThat(self.fake_protocol.send_beacon, MockNotCalled())
-        self.assertThat(
-            self.fake_protocol.send_multicast_beacons,
-            MockCalledOnceWith(TEST_INTERFACES, verbose=True),
-        )
-
-    def test_sends_unicast_beacon(self):
-        self.run_command(
-            "-v", "-s", "1.1.1.1", "-t", "42", "-p", "4242", "127.0.0.1"
-        )
-        self.assertThat(
-            self.protocol_mock,
-            MockCalledOnceWith(
-                ANY,
-                debug=True,
-                interface="1.1.1.1",
-                port=4242,
-                process_incoming=True,
-                interfaces=TEST_INTERFACES,
-            ),
-        )
-        self.assertThat(
-            self.fake_protocol.send_multicast_beacons, MockNotCalled()
-        )
-        self.assertThat(
-            self.fake_protocol.send_beacon,
-            MockCalledOnceWith(ANY, ("::ffff:127.0.0.1", 5240)),
-        )
diff --git a/src/provisioningserver/utils/tests/test_services.py b/src/provisioningserver/utils/tests/test_services.py
index 78c3352..18b79fe 100644
--- a/src/provisioningserver/utils/tests/test_services.py
+++ b/src/provisioningserver/utils/tests/test_services.py
@@ -1182,26 +1182,7 @@ class TestBeaconingSocketProtocol(SharedSecretTestCase):
 
     @inlineCallbacks
     def test_send_multicast_beacon_sets_ipv6_source(self):
-        # Due to issues beyond my control, this test doesn't do what I expected
-        # it to do. But it's still useful for code coverage (to make sure no
-        # blatant exceptions occur in the IPv6 path).
-        # self.skipTest(
-        #    "IPv6 loopback multicast isn't working, for whatever reason.")
-        # Since we can't test IPv6 multicast on the loopback interface, another
-        # method can be used to verify that it's working:
-        # (1) sudo tcpdump -i <physical-interface> 'udp and port == 5240'
-        # (2) bin/maas-rack send-beacons -p 5240
-        # Verifying IPv6 (and IPv4) multicast group join behavior can be
-        # validated by doing something like:
-        # (1) bin/maas-rack send-beacons -t 600
-        #     (the high timeout will cause it to wait for 10 minutes)
-        # (2) ip maddr show | egrep 'ff02::15a|224.0.0.118|$'
-        # The expected result from command (2) will be that 'egrep' will
-        # highlight the MAAS multicast groups in red text. Any Ethernet
-        # interface with an assigned IPv4 address should have joined the
-        # 224.0.0.118 group. All Ethernet interfaces should have joined the
-        # 'ff02::15a' group.
-        # Note: Always use a random port for testing. (port=0)
+        self.skipTest("IPv6 loopback multicast isn't working")
         protocol = BeaconingSocketProtocol(
             reactor,
             port=0,
@@ -1217,8 +1198,7 @@ class TestBeaconingSocketProtocol(SharedSecretTestCase):
         # The loopback interface ifindex should always be 1; this is saying
         # to send an IPv6 multicast on ifIndex == 1.
         protocol.send_multicast_beacon(1, beacon, port=listen_port)
-        # Instead of skipping the test, just don't expect to receive anything.
-        # yield wait_for_rx_packets(protocol, 1)
+        yield wait_for_rx_packets(protocol, 1)
         yield protocol.stopProtocol()
 
     @inlineCallbacks

Follow ups