tests/client: test nm-cloud-setup
Some fairly rudimentary testing of nm-cloud-setup.
This commit is contained in:
@@ -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 += 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
|
CLEANFILES += src/tests/client/test-client.log
|
||||||
|
|
||||||
EXTRA_DIST += \
|
EXTRA_DIST += \
|
||||||
|
@@ -15,3 +15,20 @@ test(
|
|||||||
],
|
],
|
||||||
timeout: 120,
|
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
|
||||||
|
@@ -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.
|
# In particular, you can test also a nmcli binary installed somewhere else.
|
||||||
ENV_NM_TEST_CLIENT_NMCLI_PATH = "NM_TEST_CLIENT_NMCLI_PATH"
|
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,
|
# (optional) The test also compares tranlsated output (l10n). This requires,
|
||||||
# that you first install the translation in the right place. So, by default,
|
# 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
|
# if a test for a translation fails, it will mark the test as skipped, and not
|
||||||
@@ -140,6 +144,12 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
pexpect = None
|
pexpect = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
from http.server import HTTPServer
|
||||||
|
from http.server import BaseHTTPRequestHandler
|
||||||
|
except ImportError:
|
||||||
|
HTTPServer = None
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
@@ -164,6 +174,14 @@ class PathConfiguration:
|
|||||||
assert os.path.exists(v), 'Cannot find test server at "%s"' % (v)
|
assert os.path.exists(v), 'Cannot find test server at "%s"' % (v)
|
||||||
return v
|
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
|
@staticmethod
|
||||||
def canonical_script_filename():
|
def canonical_script_filename():
|
||||||
p = "src/tests/client/test-client.py"
|
p = "src/tests/client/test-client.py"
|
||||||
@@ -551,6 +569,20 @@ class Configuration:
|
|||||||
pass
|
pass
|
||||||
if not os.path.exists(v):
|
if not os.path.exists(v):
|
||||||
raise Exception("Missing nmcli binary. Set NM_TEST_CLIENT_NMCLI_PATH?")
|
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:
|
elif name == ENV_NM_TEST_CLIENT_CHECK_L10N:
|
||||||
# if we test locales other than 'C', the output of nmcli depends on whether
|
# 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
|
# nmcli can load the translations. Unfortunately, I cannot find a way to
|
||||||
@@ -751,6 +783,16 @@ class NMStubServer:
|
|||||||
iface_name = ""
|
iface_name = ""
|
||||||
self.op_SetProperties([(path, [(iface_name, [(propname, value)])])])
|
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():
|
def main():
|
||||||
global dbus_session_inited
|
global dbus_session_inited
|
||||||
|
|
||||||
|
@@ -71,7 +71,6 @@ fi
|
|||||||
|
|
||||||
test -d "$BUILDDIR" || die "BUILDDIR \"$BUILDDIR\" does not exist?"
|
test -d "$BUILDDIR" || die "BUILDDIR \"$BUILDDIR\" does not exist?"
|
||||||
test -d "$SRCDIR" || die "SRCDIR \"$SRCDIR\" 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
|
if test -f "$BUILDDIR/src/libnm-client-impl/.libs/libnm.so" ; then
|
||||||
LIBDIR="$BUILDDIR/src/libnm-client-impl/.libs"
|
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/\""
|
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_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 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 LD_LIBRARY_PATH="$LIBDIR${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
|
||||||
export NM_TEST_CLIENT_BUILDDIR="$BUILDDIR"
|
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
|
# 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
|
# this seems to perform some slow setup during the first run. If we do that
|
||||||
# during the test, it will timeout and fail.
|
# 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
|
# 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
|
# afterwards. The only reason is that when you run with `make -j` that the
|
||||||
|
Reference in New Issue
Block a user