diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2023-03-02 19:35:38 +0100 |
---|---|---|
committer | Lubomir Rintel <lkundrak@v3.sk> | 2023-03-21 23:35:42 +0100 |
commit | d89d42bf23170b4923f71bc415fe071f7c03978a (patch) | |
tree | 4c56af7e6736d71e28bc30c0114af7737ccfe16b | |
parent | ad6878d50a10c0a6d0c36c3487d41ebce5f2ee74 (diff) | |
download | NetworkManager-d89d42bf23170b4923f71bc415fe071f7c03978a.tar.gz |
tests/client: test nm-cloud-setup
Some fairly rudimentary testing of nm-cloud-setup.
-rw-r--r-- | Makefile.am | 7 | ||||
-rw-r--r-- | src/tests/client/meson.build | 17 | ||||
-rwxr-xr-x | src/tests/client/test-client.py | 161 | ||||
-rwxr-xr-x | src/tests/client/test-client.sh | 5 |
4 files changed, 188 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am index 0f827c6763..cd30c7201e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5472,6 +5472,13 @@ check-local-tests-client: src/nmcli/nmcli src/tests/client/test-client.py check_local += check-local-tests-client +check-local-tests-cloud-setup: src/nm-cloud-setup/nm-cloud-setup src/tests/client/test-client.py + LIBTOOL="$(LIBTOOL)" "$(srcdir)/src/tests/client/test-client.sh" "$(builddir)" "$(srcdir)" "$(PYTHON)" -- TestNmCloudSetup + +if BUILD_NM_CLOUD_SETUP +check_local += check-local-tests-cloud-setup +endif + CLEANFILES += src/tests/client/test-client.log EXTRA_DIST += \ diff --git a/src/tests/client/meson.build b/src/tests/client/meson.build index 6a6891354d..1c349cc1ee 100644 --- a/src/tests/client/meson.build +++ b/src/tests/client/meson.build @@ -15,3 +15,20 @@ test( ], timeout: 120, ) + +if enable_nm_cloud_setup + test( + 'check-local-tests-cloud-setup', + find_program(join_paths(source_root, 'src/tests/client/test-client.sh')), + args: [ + build_root, + source_root, + python.path(), + '--', + 'TestNmCloudSetup', + ], + env: [ + 'LIBTOOL=', + ], + ) +endif diff --git a/src/tests/client/test-client.py b/src/tests/client/test-client.py index 859a5280be..e603203e3e 100755 --- a/src/tests/client/test-client.py +++ b/src/tests/client/test-client.py @@ -68,6 +68,10 @@ ENV_NM_TEST_CLIENT_BUILDDIR = "NM_TEST_CLIENT_BUILDDIR" # In particular, you can test also a nmcli binary installed somewhere else. ENV_NM_TEST_CLIENT_NMCLI_PATH = "NM_TEST_CLIENT_NMCLI_PATH" +# (optional) Path to nm-cloud-setup. By default, it looks for nm-cloud-setup +# in build dir. +ENV_NM_TEST_CLIENT_CLOUD_SETUP_PATH = "NM_TEST_CLIENT_CLOUD_SETUP_PATH" + # (optional) The test also compares tranlsated output (l10n). This requires, # that you first install the translation in the right place. So, by default, # if a test for a translation fails, it will mark the test as skipped, and not @@ -140,6 +144,12 @@ try: except ImportError: pexpect = None +try: + from http.server import HTTPServer + from http.server import BaseHTTPRequestHandler +except ImportError: + HTTPServer = None + ############################################################################### @@ -165,6 +175,14 @@ class PathConfiguration: return v @staticmethod + def test_cloud_meta_mock_path(): + v = os.path.abspath( + PathConfiguration.top_srcdir() + "/tools/test-cloud-meta-mock.py" + ) + assert os.path.exists(v), 'Cannot find cloud metadata mock server at "%s"' % (v) + return v + + @staticmethod def canonical_script_filename(): p = "src/tests/client/test-client.py" assert (PathConfiguration.top_srcdir() + "/" + p) == os.path.abspath(__file__) @@ -551,6 +569,20 @@ class Configuration: pass if not os.path.exists(v): raise Exception("Missing nmcli binary. Set NM_TEST_CLIENT_NMCLI_PATH?") + elif name == ENV_NM_TEST_CLIENT_CLOUD_SETUP_PATH: + v = os.environ.get(ENV_NM_TEST_CLIENT_CLOUD_SETUP_PATH, None) + if v is None: + try: + v = os.path.abspath( + self.get(ENV_NM_TEST_CLIENT_BUILDDIR) + + "/src/nm-cloud-setup/nm-cloud-setup" + ) + except: + pass + if not os.path.exists(v): + raise Exception( + "Missing nm-cloud-setup binary. Set NM_TEST_CLIENT_CLOUD_SETUP_PATH?" + ) elif name == ENV_NM_TEST_CLIENT_CHECK_L10N: # if we test locales other than 'C', the output of nmcli depends on whether # nmcli can load the translations. Unfortunately, I cannot find a way to @@ -751,6 +783,16 @@ class NMStubServer: iface_name = "" self.op_SetProperties([(path, [(iface_name, [(propname, value)])])]) + def addAndActivateConnection( + self, connection, device, specific_object="", delay=None + ): + if delay is not None: + self.op_SetActiveConnectionStateChangedDelay(device, delay) + nm_iface = self._conn_get_main_object(self._conn) + self.op_AddAndActivateConnection( + connection, device, specific_object, dbus_iface=nm_iface + ) + ############################################################################### @@ -2094,6 +2136,125 @@ class TestNmcli(TestNmClient): ############################################################################### +class TestNmCloudSetup(TestNmClient): + def cloud_setup_test(func): + """ + Runs the mock NetworkManager along with a mock cloud metadata service. + """ + + def f(self): + if pexpect is None: + raise unittest.SkipTest("pexpect not available") + + s = socket.socket() + s.set_inheritable(True) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + s.bind(("localhost", 0)) + + # The same value as Python's TCPServer uses. + # Chosen by summoning the sprit of TCP under influence of + # hallucinogenic substances. + s.listen(5) + + def pass_socket(): + os.dup2(s.fileno(), 3, inheritable=True) + + service_path = PathConfiguration.test_cloud_meta_mock_path() + env = os.environ.copy() + env["LISTEN_FDS"] = "1" + p = subprocess.Popen( + [sys.executable, service_path], + stdin=subprocess.PIPE, + env=env, + pass_fds=(s.fileno(),), + preexec_fn=pass_socket, + ) + + self.md_url = "http://%s:%d" % s.getsockname() + s.close() + + self.srv_start() + func(self) + self._nm_test_post() + + p.terminate() + p.wait() + + return f + + @cloud_setup_test + def test_ec2(self): + + # Add a device with an active connection that has IPv4 configured + self.srv.op_AddObj("WiredDevice", iface="eth0") + self.srv.addAndActivateConnection( + { + "connection": {"type": "802-3-ethernet", "id": "con-eth0"}, + "ipv4": {"method": "auto"}, + }, + "/org/freedesktop/NetworkManager/Devices/1", + delay=0, + ) + + # The second connection has no IPv4 + self.srv.op_AddObj("WiredDevice", iface="eth1") + self.srv.addAndActivateConnection( + {"connection": {"type": "802-3-ethernet", "id": "con-eth1"}}, + "/org/freedesktop/NetworkManager/Devices/2", + "", + delay=0, + ) + + # Run nm-cloud-setup for the first time + nmc = self.call_pexpect( + ENV_NM_TEST_CLIENT_CLOUD_SETUP_PATH, + [], + { + "NM_CLOUD_SETUP_EC2_HOST": self.md_url, + "NM_CLOUD_SETUP_LOG": "trace", + "NM_CLOUD_SETUP_EC2": "yes", + }, + ) + + nmc.pexp.expect("provider ec2 detected") + nmc.pexp.expect("found interfaces: 9E:C0:3E:92:24:2D, 53:E9:7E:52:8D:A8") + nmc.pexp.expect("get-config: starting") + nmc.pexp.expect("get-config: success") + nmc.pexp.expect("meta data received") + # One of the devices has no IPv4 configuration to be modified + nmc.pexp.expect("device has no suitable applied connection. Skip") + # The other one was lacking an address set it up. + nmc.pexp.expect("some changes were applied for provider ec2") + nmc.pexp.expect(pexpect.EOF) + + # Run nm-cloud-setup for the second time + nmc = self.call_pexpect( + ENV_NM_TEST_CLIENT_CLOUD_SETUP_PATH, + [], + { + "NM_CLOUD_SETUP_EC2_HOST": self.md_url, + "NM_CLOUD_SETUP_LOG": "trace", + "NM_CLOUD_SETUP_EC2": "yes", + }, + ) + + nmc.pexp.expect("provider ec2 detected") + nmc.pexp.expect("found interfaces: 9E:C0:3E:92:24:2D, 53:E9:7E:52:8D:A8") + nmc.pexp.expect("get-config: starting") + nmc.pexp.expect("get-config: success") + nmc.pexp.expect("meta data received") + # No changes this time + nmc.pexp.expect('device needs no update to applied connection "con-eth0"') + nmc.pexp.expect("no changes were applied for provider ec2") + nmc.pexp.expect(pexpect.EOF) + + Util.valgrind_check_log(nmc.valgrind_log, "test_ec2") + + +############################################################################### + + def main(): global dbus_session_inited diff --git a/src/tests/client/test-client.sh b/src/tests/client/test-client.sh index a636f5fb93..dd08e4d889 100755 --- a/src/tests/client/test-client.sh +++ b/src/tests/client/test-client.sh @@ -71,7 +71,6 @@ fi test -d "$BUILDDIR" || die "BUILDDIR \"$BUILDDIR\" does not exist?" test -d "$SRCDIR" || die "SRCDIR \"$SRCDIR\" does not exist?" -test -f "$BUILDDIR/src/nmcli/nmcli" || die "\"$BUILDDIR/src/nmcli/nmcli\" does not exist?" if test -f "$BUILDDIR/src/libnm-client-impl/.libs/libnm.so" ; then LIBDIR="$BUILDDIR/src/libnm-client-impl/.libs" @@ -84,6 +83,7 @@ fi mkdir -p "$BUILDDIR/src/tests/client/" || die "failure to create build output directory \"$BUILDDIR/src/tests/client/\"" export NM_TEST_CLIENT_NMCLI_PATH="$BUILDDIR/src/nmcli/nmcli" +export NM_TEST_CLIENT_CLOUD_SETUP_PATH="$BUILDDIR/src/nm-cloud-setup/nm-cloud-setup" export GI_TYPELIB_PATH="$BUILDDIR/src/libnm-client-impl${GI_TYPELIB_PATH:+:$GI_TYPELIB_PATH}" export LD_LIBRARY_PATH="$LIBDIR${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" export NM_TEST_CLIENT_BUILDDIR="$BUILDDIR" @@ -91,7 +91,8 @@ export NM_TEST_CLIENT_BUILDDIR="$BUILDDIR" # Run nmcli at least once. With libtool, nmcli is a shell script and with LTO # this seems to perform some slow setup during the first run. If we do that # during the test, it will timeout and fail. -"$NM_TEST_CLIENT_NMCLI_PATH" --version &>/dev/null +"$NM_TEST_CLIENT_NMCLI_PATH" --version &>/dev/null || : +"$NM_TEST_CLIENT_CLOUD_SETUP_PATH" --invalid &>/dev/null || : # we first collect all the output in "test-client.log" and print it at once # afterwards. The only reason is that when you run with `make -j` that the |