Adam Collard has proposed merging ~adam-collard/maas-ci/+git/system-tests:lxd-logger-name into ~maas-committers/maas-ci/+git/system-tests:master.
Commit message: Unify name of instance_name lxd: configure named logger for all instance-related LXD ops Requested reviews: MAAS Committers (maas-committers) For more details, see: https://code.launchpad.net/~adam-collard/maas-ci/+git/system-tests/+merge/435598 -- Your team MAAS Committers is requested to review the proposed merge of ~adam-collard/maas-ci/+git/system-tests:lxd-logger-name into ~maas-committers/maas-ci/+git/system-tests:master.
diff --git a/systemtests/lxd.py b/systemtests/lxd.py index 03a5f1d..017a551 100644 --- a/systemtests/lxd.py +++ b/systemtests/lxd.py @@ -42,9 +42,10 @@ class CLILXD: def __init__(self, logger: logging.Logger): self.logger = logger - def container_exists(self, name: str) -> bool: + def container_exists(self, instance_name: str) -> bool: + logger = self.logger.getChild(instance_name) try: - self._run(["lxc", "info", name]) + self._run(["lxc", "info", instance_name], logger=logger) except subprocess.CalledProcessError: return False else: @@ -68,8 +69,9 @@ class CLILXD: user_data: Optional[str] = None, profile: Optional[str] = None, ) -> str: + logger = self.logger.getChild(name) if not self.container_exists(name): - self.logger.info(f"Creating container {name} (from {image})...") + logger.info(f"Creating container {name} (from {image})...") cmd = [ "lxc", "launch", @@ -82,11 +84,11 @@ class CLILXD: if profile is not None: cmd.extend(["-p", profile]) cmd.append(name) - self._run(cmd) - self.logger.info(f"Container {name} created.") - self.logger.info("Waiting for boot to finish...") + self._run(cmd, logger=logger) + logger.info(f"Container {name} created.") + logger.info("Waiting for boot to finish...") - @retry(exceptions=CloudInitDisabled, tries=120, delay=1, logger=self.logger) + @retry(exceptions=CloudInitDisabled, tries=120, delay=1, logger=logger) def _cloud_init_wait() -> None: process = self.execute( name, ["timeout", "2000", "cloud-init", "status", "--wait", "--long"] @@ -98,7 +100,7 @@ class CLILXD: ) _cloud_init_wait() - self.logger.info("Boot finished.") + logger.info("Boot finished.") return name def get_or_create( @@ -114,7 +116,7 @@ class CLILXD: def push_file( self, - container: str, + instance_name: str, source_file: str, target_file: str, uid: int = 0, @@ -130,16 +132,17 @@ class CLILXD: "--mode", mode, source_file, - f"{container}{target_file}", + f"{instance_name}{target_file}", ] if create_dirs: args.append("--create-dirs") - self._run(["lxc", "file", "--quiet", "push", *args]) + logger = self.logger.getChild(instance_name) + self._run(["lxc", "file", "--quiet", "push", *args], logger=logger) def push_text_file( self, - container: str, + instance_name: str, content: str, target_file: str, uid: int = 0, @@ -149,24 +152,25 @@ class CLILXD: source_file.write(content.encode()) source_file.seek(0) self.push_file( - container, + instance_name, source_file.name, target_file, uid=uid, gid=gid, ) - def file_exists(self, container: str, file_path: str) -> bool: + def file_exists(self, instance_name: str, file_path: str) -> bool: try: - self.quietly_execute(container, ["stat", file_path]) + self.quietly_execute(instance_name, ["stat", file_path]) except subprocess.CalledProcessError: return False else: return True def pull_file( - self, container: str, file_path: str, local_path: str + self, instance_name: str, file_path: str, local_path: str ) -> subprocess.CompletedProcess[str]: + logger = self.logger.getChild(instance_name) return self._run( [ "lxc", @@ -174,12 +178,14 @@ class CLILXD: "--quiet", "pull", "-r", - f"{container}/{file_path}", + f"{instance_name}/{file_path}", local_path, ], + logger=logger, ) - def get_file_contents(self, container: str, file_path: str) -> str: + def get_file_contents(self, instance_name: str, file_path: str) -> str: + logger = self.logger.getChild(instance_name) filename = os.path.basename(file_path) with tempfile.TemporaryDirectory() as tempdir: self._run( @@ -188,9 +194,10 @@ class CLILXD: "file", "--quiet", "pull", - f"{container}{file_path}", + f"{instance_name}{file_path}", f"{tempdir}/", ], + logger=logger, ) with open(os.path.join(tempdir, filename), "r") as f: return f.read() @@ -219,9 +226,9 @@ class CLILXD: return _retry_bad_handshake() def _get_lxc_command( - self, container: str, environment: Optional[dict[str, str]] + self, instance_name: str, environment: Optional[dict[str, str]] ) -> list[str]: - lxc_command = ["lxc", "exec", "--force-noninteractive", container] + lxc_command = ["lxc", "exec", "--force-noninteractive", instance_name] if environment is not None: for key, value in environment.items(): lxc_command.extend(["--env", f"{key}={value}"]) @@ -230,13 +237,13 @@ class CLILXD: def execute( self, - container: str, + instance_name: str, command: list[str], environment: Optional[dict[str, str]] = None, ) -> subprocess.CompletedProcess[str]: __tracebackhide__ = True - logger = self.logger.getChild(container) - lxc_command = self._get_lxc_command(container, environment) + logger = self.logger.getChild(instance_name) + lxc_command = self._get_lxc_command(instance_name, environment) # Suppress logging of the lxc wrapper for clearer logs executor = partial(self._run, command, prefix=lxc_command, logger=logger) @@ -244,13 +251,13 @@ class CLILXD: def quietly_execute( self, - container: str, + instance_name: str, command: list[str], environment: Optional[dict[str, str]] = None, ) -> subprocess.CompletedProcess[str]: """Execute a command without logging it.""" __tracebackhide__ = True - lxc_command = self._get_lxc_command(container, environment) + lxc_command = self._get_lxc_command(instance_name, environment) executor = partial( subprocess.run, @@ -262,18 +269,21 @@ class CLILXD: ) return self._run_with_logger(executor, None) - def delete(self, instance: str) -> None: - self._run(["lxc", "delete", "--force", instance]) + def delete(self, instance_name: str) -> None: + logger = self.logger.getChild(instance_name) + self._run(["lxc", "delete", "--force", instance_name], logger=logger) - def get_ip_address(self, container: str) -> str: - @retry( - exceptions=RuntimeError, tries=30, delay=2, backoff=1.1, logger=self.logger - ) + def get_ip_address(self, instance_name: str) -> str: + logger = self.logger.getChild(instance_name) + + @retry(exceptions=RuntimeError, tries=30, delay=2, backoff=1.1, logger=logger) def _get_ip_address() -> str: - result = self._run(["lxc", "list", "--format", "json", container]) + result = self._run( + ["lxc", "list", "--format", "json", instance_name], logger=logger + ) # lxc list does partial match, so we still need to find the entry for entry in json.loads(result.stdout): - if entry["name"] != container: + if entry["name"] != instance_name: continue for address in entry["state"]["network"]["eth0"]["addresses"]: self.logger.info(f"Considering address: {address}") @@ -315,34 +325,38 @@ class CLILXD: ["lxc", "profile", "device", "remove", profile_name, device_name], ) - def collect_sos_report(self, container: str, output: str) -> None: + def collect_sos_report(self, instance_name: str, output: str) -> None: container_tmp = "/tmp/sosreport" output_dir = Path(f"{output}/sosreport") - self.execute(container, ["apt", "install", "--yes", "sosreport"]) - self.execute(container, ["rm", "-rf", container_tmp]) - self.execute(container, ["mkdir", "-p", container_tmp]) + self.execute(instance_name, ["apt", "install", "--yes", "sosreport"]) + self.execute(instance_name, ["rm", "-rf", container_tmp]) + self.execute(instance_name, ["mkdir", "-p", container_tmp]) self.execute( - container, + instance_name, ["sos", "report", "--batch", "-o", "maas", "--tmp-dir", container_tmp], ) output_dir.mkdir(parents=True, exist_ok=True) journalctl = self.execute( - container, ["journalctl", "--unit=vault", "--no-pager", "--output=cat"] + instance_name, ["journalctl", "--unit=vault", "--no-pager", "--output=cat"] ) if journalctl.stdout: (output_dir / "vault-journal").write_text(journalctl.stdout) with tempfile.TemporaryDirectory(prefix="sosreport") as tempdir: - self.pull_file(container, container_tmp, f"{tempdir}/") + self.pull_file(instance_name, container_tmp, f"{tempdir}/") for f in os.listdir(f"{tempdir}/sosreport"): os.rename(os.path.join(f"{tempdir}/sosreport", f), f"{output_dir}/{f}") def list_instance_devices(self, instance_name: str) -> list[str]: - result = self._run(["lxc", "config", "device", "list", instance_name]) + logger = self.logger.getChild(instance_name) + result = self._run( + ["lxc", "config", "device", "list", instance_name], logger=logger + ) return result.stdout.splitlines() def add_instance_device( self, instance_name: str, name: str, device_config: DeviceConfig ) -> None: + logger = self.logger.getChild(instance_name) self._run( [ "lxc", @@ -353,11 +367,13 @@ class CLILXD: name, device_config["type"], ] - + fmt_lxd_options(device_config) + + fmt_lxd_options(device_config), + logger=logger, ) def remove_instance_device(self, instance_name: str, device_name: str) -> None: """Remove a device from an instance.""" + logger = self.logger.getChild(instance_name) @retry( exceptions=subprocess.CalledProcessError, @@ -367,7 +383,8 @@ class CLILXD: ) def _remove_device() -> subprocess.CompletedProcess[str]: return self._run( - ["lxc", "config", "device", "remove", instance_name, device_name] + ["lxc", "config", "device", "remove", instance_name, device_name], + logger=logger, ) _remove_device() @@ -379,12 +396,15 @@ class CLILXD: return instances def create_vm(self, instance_name: str, config: dict[str, str]) -> None: + logger = self.logger.getChild(instance_name) args: list[str] = [] profile: Optional[str] = config.pop("profile", None) if profile: args += ["-p", profile] args += list(chain.from_iterable(("-c", f"{k}={v}") for k, v in config.items())) - self._run(["lxc", "init", "--empty", "--vm", instance_name] + args) + self._run( + ["lxc", "init", "--empty", "--vm", instance_name] + args, logger=logger + ) self._run( [ "lxc", @@ -394,22 +414,30 @@ class CLILXD: instance_name, "eth0", "boot.priority=10", - ] + ], + logger=logger, ) def start(self, instance_name: str) -> subprocess.CompletedProcess[str]: - return self._run(["lxc", "start", instance_name]) + logger = self.logger.getChild(instance_name) + return self._run(["lxc", "start", instance_name], logger=logger) def stop( self, instance_name: str, force: bool = False ) -> subprocess.CompletedProcess[str]: + logger = self.logger.getChild(instance_name) argv = ["lxc", "stop", instance_name] if force: argv.append("--force") - return self._run(argv) + return self._run(argv, logger=logger) def instance_status(self, instance_name: str) -> str: +<<<<<<< systemtests/lxd.py result = self._run(["lxc", "info", instance_name]) +======= + logger = self.logger.getChild(instance_name) + result = self._run(["lxc", "info", instance_name], logger=logger) +>>>>>>> systemtests/lxd.py for line in result.stdout.splitlines(): key, value = line.split(": ", 1) if key == "Status": @@ -428,10 +456,11 @@ class CLILXD: def restart( self, instance_name: str, force: bool = False ) -> subprocess.CompletedProcess[str]: + logger = self.logger.getChild(instance_name) argv = ["lxc", "restart", instance_name] if force: argv.append("--force") - return self._run(argv) + return self._run(argv, logger=logger) def fmt_lxd_options(cfg: DeviceConfig) -> list[str]:
-- Mailing list: https://launchpad.net/~sts-sponsors Post to : sts-sponsors@lists.launchpad.net Unsubscribe : https://launchpad.net/~sts-sponsors More help : https://help.launchpad.net/ListHelp