sts-sponsors team mailing list archive
-
sts-sponsors team
-
Mailing list archive
-
Message #05099
[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