Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor integration tests to use pycloudlib LXD #1241

Merged
merged 3 commits into from Dec 1, 2020

Conversation

lucasmoura
Copy link
Contributor

Refactor integration tests to use pycloudlib LXD implementation. This also allows us to test enabling FIPS for xenial.

PS: This PR depends on the following pycloudlib PR

Location of the private key path to use. If None, the location
will be a default location.
"""
pub_key_path = "lxd-pubkey"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you mentioned in passing, the integration tests currently take 4 times as long running via ssh to the lxd instance instead of lxc exec. Should this method be a noop (pass) or not be called in typical lxd testing used in our per-PR integration tests? We could rely on the ssh-based lxd communication in either our daily CRON or daily jenkins tests.

Copy link
Collaborator

@blackboxsw blackboxsw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a quick pass on this. will get detailed review tomorrow.

features/cloud.py Outdated Show resolved Hide resolved
@lucasmoura
Copy link
Contributor Author

@blackboxsw One idea that I had is that we can use the ssh option only for vm tests, since it is only those tests that require the use of ssh.

To make that possible, we need to first merge this PR

@lucasmoura lucasmoura force-pushed the use-lxd-support-from-pycloudlib branch 2 times, most recently from 4446fd6 to e24d7f2 Compare November 24, 2020 14:36
@lucasmoura
Copy link
Contributor Author

@blackboxsw I have update the code with the refactoring and FIPS tests.

Right now, the FIPS Updates upgrade test is just assuring that we end up in a scenario were we have the FIPS metapackage uninstalled because of the do-release-upgrade issue. Once it has been fixed, I can update the test without an issue.

Copy link
Collaborator

@blackboxsw blackboxsw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you mentioned in chat. something is occuring with the shlex usage when trying to run cmds that emit json since we are splitting the cmdstring blindly on spaces. I've suggested a few changes inline but I think we also may have to sort to remaining checks in features/environment which check for a possible path where cloud_api is not set since I don't think we would have that path anymore right?

  • features/environment: (before_all) if context.config.cloud_api:
  • features/environment:583 (_install_uat_in_container) if not config.cloud_api

@@ -116,10 +123,12 @@ def launch(
:returns:
An cloud provider instance
"""
inst = self._create_instance(series, image_name, user_data)
inst = self._create_instance(
series, instance_name, image_name, user_data
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's use names kwargs here so if we change call signature or param ordering in the future, we don't break.
I get a bad feeling every time I see positional arguments re-ordered because we inserted a new one earlier sequentiall than previous params.

Suggested change
series, instance_name, image_name, user_data
series=series, instance_name=instance_name, image_name=image_name, user_data=user_data

@@ -182,7 +182,7 @@ class FIPSUpdatesEntitlement(FIPSCommonEntitlement):

name = "fips-updates"
title = "FIPS Updates"
origin = "UbuntuFIPSUpdates"
origin = "UbuntuFIPS"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's please put a comment in here # RELEASE_BLOCKER and reference your RT or a new ua-client issue so we are aware of the blocker

Suggested change
origin = "UbuntuFIPS"
origin = "UbuntuFIPS" # RELEASE_BLOCKER RT: #128770



class LXDContainer(_LXD):
name = "lxd-virtual-machine"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
name = "lxd-virtual-machine"
name = "lxd-container"

pub_key, priv_key = self.api.create_key_pair()

with open(pub_key_path, "w") as f:
f.write(pub_key)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably want to os.chmod these as 600 so that developers could use them on the cmdline to access instances using ssh -i lxd-pubkey ubuntu@<ip>

Comment on lines 598 to 604
@property
def api(self) -> pycloudlib.cloud.BaseCloud:
"""Return the api used to interact with the cloud provider."""
if self._api is None:
self._api = pycloudlib.LXDVirtualMachine(tag=self.tag)

return self._api
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might be able to define this simply in either in _LXD base class or even Cloud if we use a class attr to define the pycloublib.*Cloud callable to create

index 38114a6..c2b8600 100644
--- a/features/cloud.py
+++ b/features/cloud.py
@@ -29,6 +29,7 @@ class Cloud:
     name = ""
     pro_ids_path = ""
     env_vars: "Tuple[str, ...]" = ()
+    pycloudlib_cls = None  # type: pycloudlib.cloud.BaseCloud
 
     def __init__(
         self,
@@ -64,7 +65,13 @@ class Cloud:
     @property
     def api(self) -> pycloudlib.cloud.BaseCloud:
         """Return the api used to interact with the cloud provider."""
-        raise NotImplementedError
+        if self.pycloudlib_cls is None:
+            raise NotImplementedError
+        if self._api is None:
+            self._api = self.pycloudlib_cls(
+                tag=self.tag, timestamp_suffix=self.timestamp_suffix
+            )
+        return self.api
 
     def manage_ssh_key(self, private_key_path: "Optional[str]" = None) -> None:
         """Create and manage ssh key pairs to be used in the cloud provider.
@@ -496,8 +503,6 @@ class Azure(Cloud):
 
 
 class _LXD(Cloud):
-    name = "_lxd"
-
     def _create_instance(
         self,
         series: str,
@@ -573,6 +578,7 @@ class _LXD(Cloud):
 
 class LXDVirtualMachine(_LXD):
     name = "lxd-virtual-machine"
+    pycloudlib_cls = pycloudlib.LXDVirtualMachine
 
     def manage_ssh_key(self, private_key_path: "Optional[str]" = None) -> None:
         """Create and manage ssh key pairs to be used in the cloud provider.
@@ -606,6 +612,7 @@ class LXDVirtualMachine(_LXD):
 
 class LXDContainer(_LXD):
     name = "lxd-virtual-machine"
+    pycloudlib_cls = pycloudlib.LXDContainer
 
     def manage_ssh_key(self, private_key_path: "Optional[str]" = None) -> None:
         """Create and manage ssh key pairs to be used in the cloud provider.

def api(self) -> pycloudlib.cloud.BaseCloud:
"""Return the api used to interact with the cloud provider."""
if self._api is None:
self._api = pycloudlib.LXDContainer(tag=self.tag)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's also not forget timestamp_suffix=self.timestamp_suffix

def api(self) -> pycloudlib.cloud.BaseCloud:
"""Return the api used to interact with the cloud provider."""
if self._api is None:
self._api = pycloudlib.LXDVirtualMachine(tag=self.tag)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't forget timestamp_suffix=self.timestamp_suffix


from uaclient.defaults import DEFAULT_CONFIG_FILE


CONTAINER_PREFIX = "behave-test-"
CONTAINER_PREFIX = "ubuntu-behave-test-"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why change this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just to guarantee that the instance name will be properly parsed by this regex:
https://github.com/canonical/pycloudlib/blob/master/pycloudlib/lxd/cloud.py#L580

@lucasmoura
Copy link
Contributor Author

@blackboxsw Thanks for the review and great catch on the leftover code for checking cloud_api.

I have updated the code and I think instead of worrying about shellify at the moment, we should wait for this pycloudlib PR to land. When that happens, we will no longer need the execute_command method anymore

@lucasmoura lucasmoura force-pushed the use-lxd-support-from-pycloudlib branch 2 times, most recently from 4bfc023 to a0d7522 Compare November 27, 2020 18:00
Currently, our integration tests are using our own
abstraction to handle LXD containers and vms. Since
all other cloud we interact with are using pycloudlib,
we have made the decision to apply that for LXD support
as well.
The pin priority is not working for FIPS Updates
because the preferences file we are creating has the
wrong origin data. The product requires origin as
"UbuntuFIPS" but we are using "UbuntuFIPSUpdates"
Add FIPS tests for xenial and upgrade test from xenial
to bionic when FIPS is enabled in the system. However,
FIPS Updates is not currently working when upgrading
from xenial to bionic due to a problem on do-release-upgrade
where we fail to access the right repo for FIPS Updates
during the upgrade and end up disabling the ppa, causing
some package, e.g. ubuntu-fips, to be removed.
Copy link
Collaborator

@blackboxsw blackboxsw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much simpler to use the pycloudlib to rule all the platforms. Thanks for this work!

@blackboxsw blackboxsw merged commit 4ba6698 into master Dec 1, 2020
@lucasmoura lucasmoura deleted the use-lxd-support-from-pycloudlib branch December 1, 2020 13:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants