Tox + Integration testing
This commit implements a VNF Descriptor-driven integration
test framework, which will lead to integration tests being able
to run via jenkins, and more robust testing in general.
N2VC:
- Allow the use of an event loop passed when instantiating N2VC
- Refactor the execution of the initial-config-primitive so that it can
be easily re-run, such as the case of when a proxy charm is deployed
before the VNF's VM is created.
- Refactor GetPrimitiveStatus, to return the status (queued, running,
complete, failed) of a primitive.
- Add GetPrimitiveOutput, to return the output of a completed primitive
- Fix model disconnection when executing a primitive (it was happening
in the wrong scope)
- Fix wait_for_application, which was previously unused and broken
- Add support for parameter's 'data-type' field
- Add support for better SSH key management, allowing for a proxy charm
to be deployed before the VNF, so that it's public SSH key can be
injected when the VNF's VM is created.
Integration Tests:
The integration tests are intended to exercise the expected
functionality of a VNF/charm: deploy the charm, configure it as required
(i.e., ssh credentials), and execute the VNF's
initial-config-primitives.
- test_native_charm: deploy a native charm to a juju-managed machine and
verify primitive execution works
- test_proxy_charm: deploy a proxy charm, configured to talk to a remote
machine, and verify primitive execution works
- test_metrics_native: deploy a native charm and collect a metric
- test_metrics_proxy: deploy a proxy charm and collect a metric from the
vnf
- test_no_initial-config-primitive: deploy a vnf without an
initial-config-primitive
- test_non-string_parameter: deploy a vnf with a non-string parameter in
initial-config-primitive
- test_no_parameter: deploy a vnf with a primitive with no parameters
General:
- Add a build target to tox.ini so that a .deb is built via Jenkins
TODO (in a follow-up commit):
- test multi-vdu, multi-charm
- test deploying a native charm to a manually-provisioned machine
- Update inline pydoc
- Add more integration tests
- Add global per-test timeout to catch stalled tests
Signed-off-by: Adam Israel <adam.israel@canonical.com>
Change-Id: Id322b45d65c44714e8051fc5764f8c20b76d846c
diff --git a/tests/test_lxd.py b/tests/test_lxd.py
new file mode 100644
index 0000000..f68fa3a
--- /dev/null
+++ b/tests/test_lxd.py
@@ -0,0 +1,96 @@
+"""
+This test exercises LXD, to make sure that we can:
+1. Create a container profile
+2. Launch a container with a profile
+3. Stop a container
+4. Destroy a container
+5. Delete a container profile
+
+"""
+import logging
+# import os
+import pytest
+from . import base
+import subprocess
+import shlex
+import tempfile
+
+
+@pytest.mark.asyncio
+async def test_lxd():
+
+ container = base.create_lxd_container(name="test-lxd")
+ assert container is not None
+
+ # Get the hostname of the container
+ hostname = container.name
+
+ # Delete the container
+ base.destroy_lxd_container(container)
+
+ # Verify the container is deleted
+ client = base.get_lxd_client()
+ assert client.containers.exists(hostname) is False
+
+
+@pytest.mark.asyncio
+async def test_lxd_ssh():
+
+ with tempfile.TemporaryDirectory() as tmp:
+ try:
+ # Create a temporary keypair
+ cmd = shlex.split(
+ "ssh-keygen -t rsa -b 4096 -N '' -f {}/id_lxd_rsa".format(
+ tmp,
+ )
+ )
+ subprocess.check_call(cmd)
+ except subprocess.CalledProcessError as e:
+ logging.debug(e)
+ assert False
+
+ # Slurp the public key
+ public_key = None
+ with open("{}/id_lxd_rsa.pub".format(tmp), "r") as f:
+ public_key = f.read()
+
+ assert public_key is not None
+
+ # Create the container with the keypair injected via profile
+ container = base.create_lxd_container(
+ public_key=public_key,
+ name="test-lxd"
+ )
+ assert container is not None
+
+ # Get the hostname of the container
+ hostname = container.name
+
+ addresses = container.state().network['eth0']['addresses']
+ # The interface may have more than one address, but we only need
+ # the first one for testing purposes.
+ ipaddr = addresses[0]['address']
+
+ # Verify we can SSH into container
+ try:
+ cmd = shlex.split(
+ "ssh -i {}/id_lxd_rsa {} root@{} hostname".format(
+ tmp,
+ "-oStrictHostKeyChecking=no",
+ ipaddr,
+ )
+ )
+ subprocess.check_call(cmd)
+ except subprocess.CalledProcessError as e:
+ logging.debug(e)
+ assert False
+
+ # Delete the container
+ base.destroy_lxd_container(container)
+
+ # Verify the container is deleted
+ client = base.get_lxd_client()
+ assert client.containers.exists(hostname) is False
+
+ # Verify the container profile is deleted
+ assert client.profiles.exists(hostname) is False