From 7736b83f0aa363aeb26581132b476dcf9317d69c Mon Sep 17 00:00:00 2001 From: paull Date: Mon, 9 Dec 2024 09:22:54 -0800 Subject: [PATCH 1/6] # This is a combination of 2 commits. # This is the 1st commit message: Added ip_power control for BareMetal platform # The commit message #2 will be skipped: # Added tftp deployment on BareMetal platform (#3422) # # Co-authored-by: paull --- lisa/sut_orchestrator/baremetal/ip_power.py | 54 +++++++++++++++++++++ lisa/sut_orchestrator/baremetal/schema.py | 16 ++++++ 2 files changed, 70 insertions(+) create mode 100644 lisa/sut_orchestrator/baremetal/ip_power.py diff --git a/lisa/sut_orchestrator/baremetal/ip_power.py b/lisa/sut_orchestrator/baremetal/ip_power.py new file mode 100644 index 0000000000..b82d933d56 --- /dev/null +++ b/lisa/sut_orchestrator/baremetal/ip_power.py @@ -0,0 +1,54 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +from typing import Type + +import requests + +from lisa import schema +from lisa.util import ContextMixin, InitializableMixin, subclasses +from lisa.util.logger import get_logger + +from .schema import IPPowerSchema + + +class IPPower(subclasses.BaseClassWithRunbookMixin, ContextMixin, InitializableMixin): + def __init__(self, runbook: IPPowerSchema) -> None: + super().__init__(runbook=runbook) + self._log = get_logger("cluster", self.__class__.__name__) + + @classmethod + def type_schema(cls) -> Type[schema.TypedSchema]: + return IPPowerSchema + + def on(self, port: int) -> None: + raise NotImplementedError() + + def off(self, port: int) -> None: + raise NotImplementedError() + + +class Ip9285(IPPower): + def __init__(self, runbook: IPPowerSchema) -> None: + super().__init__(runbook) + self._request_cmd = ( + f"http://{runbook.hostname}/set.cmd?" + f"user={runbook.username}+pass=" + f"{runbook.password}+cmd=setpower+P6" + ) + + @classmethod + def type_name(cls) -> str: + return "Ip9285" + + @classmethod + def type_schema(cls) -> Type[schema.TypedSchema]: + return IPPowerSchema + + def on(self, port: int) -> None: + request_on = f"{self._request_cmd}{port}=1" + requests.get(request_on) + + def off(self, port: int) -> None: + request_off = f"{self._request_cmd}{port}=0" + requests.get(request_off) diff --git a/lisa/sut_orchestrator/baremetal/schema.py b/lisa/sut_orchestrator/baremetal/schema.py index 5fe7536a51..d9a8afaefd 100644 --- a/lisa/sut_orchestrator/baremetal/schema.py +++ b/lisa/sut_orchestrator/baremetal/schema.py @@ -72,6 +72,22 @@ class BootConfigSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): type: str = field(default="boot_config", metadata=field_metadata(required=True)) +@dataclass_json() +@dataclass +class IPPowerSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): + type: str = field(default="Ip9285", metadata=field_metadata(required=True)) + hostname: str = "" + username: str = "" + password: str = "" + + def __post_init__(self, *args: Any, **kwargs: Any) -> None: + add_secret(self.password) + + +class BootConfigSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): + type: str = field(default="boot_config", metadata=field_metadata(required=True)) + + @dataclass_json() @dataclass class ClusterSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): From 739ba086a170bf6b1b167000529925d07357feaa Mon Sep 17 00:00:00 2001 From: paull Date: Mon, 9 Dec 2024 16:47:03 -0800 Subject: [PATCH 2/6] Added ip_power control for BareMetal platform --- lisa/sut_orchestrator/baremetal/schema.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lisa/sut_orchestrator/baremetal/schema.py b/lisa/sut_orchestrator/baremetal/schema.py index d9a8afaefd..bf4d53c341 100644 --- a/lisa/sut_orchestrator/baremetal/schema.py +++ b/lisa/sut_orchestrator/baremetal/schema.py @@ -66,12 +66,6 @@ class KeyLoaderSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): type: str = field(default="build", metadata=field_metadata(required=True)) -@dataclass_json() -@dataclass -class BootConfigSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): - type: str = field(default="boot_config", metadata=field_metadata(required=True)) - - @dataclass_json() @dataclass class IPPowerSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): @@ -83,7 +77,9 @@ class IPPowerSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): def __post_init__(self, *args: Any, **kwargs: Any) -> None: add_secret(self.password) - + +@dataclass_json() +@dataclass class BootConfigSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): type: str = field(default="boot_config", metadata=field_metadata(required=True)) From d0e8ed34273d820c498ad55f158868736203cefc Mon Sep 17 00:00:00 2001 From: paull Date: Mon, 9 Dec 2024 09:22:54 -0800 Subject: [PATCH 3/6] Added ip_power control for BareMetal platform --- lisa/sut_orchestrator/baremetal/schema.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lisa/sut_orchestrator/baremetal/schema.py b/lisa/sut_orchestrator/baremetal/schema.py index bf4d53c341..e4ca301fa5 100644 --- a/lisa/sut_orchestrator/baremetal/schema.py +++ b/lisa/sut_orchestrator/baremetal/schema.py @@ -84,6 +84,18 @@ class BootConfigSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): type: str = field(default="boot_config", metadata=field_metadata(required=True)) +@dataclass_json() +@dataclass +class IPPowerSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): + type: str = field(default="Ip9285", metadata=field_metadata(required=True)) + hostname: str = "" + username: str = "" + password: str = "" + + def __post_init__(self, *args: Any, **kwargs: Any) -> None: + add_secret(self.password) + + @dataclass_json() @dataclass class ClusterSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): From 4338632cba816553c1572ea405b906ddb14df2b6 Mon Sep 17 00:00:00 2001 From: paulli Date: Tue, 15 Oct 2024 22:36:41 -0700 Subject: [PATCH 4/6] Added tftp deployment on BareMetal platform (#3422) Co-authored-by: paull --- lisa/sut_orchestrator/baremetal/schema.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lisa/sut_orchestrator/baremetal/schema.py b/lisa/sut_orchestrator/baremetal/schema.py index e4ca301fa5..5d51e52329 100644 --- a/lisa/sut_orchestrator/baremetal/schema.py +++ b/lisa/sut_orchestrator/baremetal/schema.py @@ -95,6 +95,10 @@ class IPPowerSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): def __post_init__(self, *args: Any, **kwargs: Any) -> None: add_secret(self.password) + +class BootConfigSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): + type: str = field(default="boot_config", metadata=field_metadata(required=True)) + @dataclass_json() @dataclass From a77a26e7d3b1feda3892fd30d244e98ca96998ec Mon Sep 17 00:00:00 2001 From: paull Date: Mon, 9 Dec 2024 09:22:54 -0800 Subject: [PATCH 5/6] Added ip_power control for BareMetal platform --- lisa/sut_orchestrator/baremetal/schema.py | 34 ----------------------- 1 file changed, 34 deletions(-) diff --git a/lisa/sut_orchestrator/baremetal/schema.py b/lisa/sut_orchestrator/baremetal/schema.py index 5d51e52329..65d8bbb336 100644 --- a/lisa/sut_orchestrator/baremetal/schema.py +++ b/lisa/sut_orchestrator/baremetal/schema.py @@ -66,40 +66,6 @@ class KeyLoaderSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): type: str = field(default="build", metadata=field_metadata(required=True)) -@dataclass_json() -@dataclass -class IPPowerSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): - type: str = field(default="Ip9285", metadata=field_metadata(required=True)) - hostname: str = "" - username: str = "" - password: str = "" - - def __post_init__(self, *args: Any, **kwargs: Any) -> None: - add_secret(self.password) - - -@dataclass_json() -@dataclass -class BootConfigSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): - type: str = field(default="boot_config", metadata=field_metadata(required=True)) - - -@dataclass_json() -@dataclass -class IPPowerSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): - type: str = field(default="Ip9285", metadata=field_metadata(required=True)) - hostname: str = "" - username: str = "" - password: str = "" - - def __post_init__(self, *args: Any, **kwargs: Any) -> None: - add_secret(self.password) - - -class BootConfigSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): - type: str = field(default="boot_config", metadata=field_metadata(required=True)) - - @dataclass_json() @dataclass class ClusterSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): From f5a0fe65c2e57a9c8e3892f729c3e1b1af1ffa12 Mon Sep 17 00:00:00 2001 From: paull Date: Mon, 9 Dec 2024 16:43:12 -0800 Subject: [PATCH 6/6] test --- lisa/sut_orchestrator/baremetal/ip_power.py | 30 +++++++++++++++------ lisa/sut_orchestrator/baremetal/schema.py | 18 +++++++++++++ 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/lisa/sut_orchestrator/baremetal/ip_power.py b/lisa/sut_orchestrator/baremetal/ip_power.py index b82d933d56..96faa27998 100644 --- a/lisa/sut_orchestrator/baremetal/ip_power.py +++ b/lisa/sut_orchestrator/baremetal/ip_power.py @@ -6,11 +6,14 @@ import requests from lisa import schema -from lisa.util import ContextMixin, InitializableMixin, subclasses +from lisa.util import ContextMixin, InitializableMixin, LisaException, subclasses from lisa.util.logger import get_logger from .schema import IPPowerSchema +REQUEST_TIMEOUT = 3 +REQUEST_SUCCESS_CODE = 200 + class IPPower(subclasses.BaseClassWithRunbookMixin, ContextMixin, InitializableMixin): def __init__(self, runbook: IPPowerSchema) -> None: @@ -21,10 +24,10 @@ def __init__(self, runbook: IPPowerSchema) -> None: def type_schema(cls) -> Type[schema.TypedSchema]: return IPPowerSchema - def on(self, port: int) -> None: + def on(self, port: str) -> None: raise NotImplementedError() - def off(self, port: int) -> None: + def off(self, port: str) -> None: raise NotImplementedError() @@ -32,7 +35,7 @@ class Ip9285(IPPower): def __init__(self, runbook: IPPowerSchema) -> None: super().__init__(runbook) self._request_cmd = ( - f"http://{runbook.hostname}/set.cmd?" + f"http://{runbook.host}/set.cmd?" f"user={runbook.username}+pass=" f"{runbook.password}+cmd=setpower+P6" ) @@ -45,10 +48,21 @@ def type_name(cls) -> str: def type_schema(cls) -> Type[schema.TypedSchema]: return IPPowerSchema - def on(self, port: int) -> None: + def on(self, port: str) -> None: request_on = f"{self._request_cmd}{port}=1" - requests.get(request_on) + self._set_ip_power(request_on) - def off(self, port: int) -> None: + def off(self, port: str) -> None: request_off = f"{self._request_cmd}{port}=0" - requests.get(request_off) + self._set_ip_power(request_off) + + def _set_ip_power(self, power_cmd: str) -> None: + try: + response = requests.get(power_cmd, timeout=REQUEST_TIMEOUT) + response.raise_for_status() + except requests.HTTPError as http_err: + raise LisaException(f"HTTP error: {http_err} in set_ip_power occurred") + except Exception as err: + raise LisaException(f"Other Error: {err} in set_ip_power occurred") + else: + self._log.debug(f"Command {power_cmd} in set_ip_power done") diff --git a/lisa/sut_orchestrator/baremetal/schema.py b/lisa/sut_orchestrator/baremetal/schema.py index 65d8bbb336..39bd365a70 100644 --- a/lisa/sut_orchestrator/baremetal/schema.py +++ b/lisa/sut_orchestrator/baremetal/schema.py @@ -66,6 +66,24 @@ class KeyLoaderSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): type: str = field(default="build", metadata=field_metadata(required=True)) +@dataclass_json() +@dataclass +class BootConfigSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): + type: str = field(default="boot_config", metadata=field_metadata(required=True)) + + +@dataclass_json() +@dataclass +class IPPowerSchema(schema.TypedSchema, schema.ExtendableSchemaMixin): + type: str = field(default="Ip9285", metadata=field_metadata(required=True)) + host: str = "" + username: str = "" + password: str = "" + + def __post_init__(self, *args: Any, **kwargs: Any) -> None: + add_secret(self.password) + + @dataclass_json() @dataclass class ClusterSchema(schema.TypedSchema, schema.ExtendableSchemaMixin):