Add security profile feature in libvirt

This commit is contained in:
AASTHA RAWAT 2024-09-24 16:32:04 +05:30 коммит произвёл Purna Pavan Chandra
Родитель 0d9420884c
Коммит 3079f43567
4 изменённых файлов: 126 добавлений и 2 удалений

Просмотреть файл

@ -48,6 +48,7 @@ class NodeContext:
vm_name: str = "" vm_name: str = ""
firmware_source_path: str = "" firmware_source_path: str = ""
firmware_path: str = "" firmware_path: str = ""
guest_vm_type: str = ""
cloud_init_file_path: str = "" cloud_init_file_path: str = ""
ignition_file_path: str = "" ignition_file_path: str = ""
os_disk_source_file_path: Optional[str] = None os_disk_source_file_path: Optional[str] = None

Просмотреть файл

@ -0,0 +1,57 @@
from dataclasses import dataclass
from typing import Any, Type, cast
from dataclasses_json import dataclass_json
from lisa import features, schema, search_space
from lisa.environment import Environment
from lisa.features.security_profile import SecurityProfileType
from lisa.sut_orchestrator.libvirt.context import get_node_context
@dataclass_json()
@dataclass()
class SecurityProfileSettings(features.SecurityProfileSettings):
def __hash__(self) -> int:
return hash(self._get_key())
def _get_key(self) -> str:
return f"{self.type}/{self.security_profile}/"
def _call_requirement_method(
self, method: search_space.RequirementMethod, capability: Any
) -> Any:
super_value: SecurityProfileSettings = super()._call_requirement_method(
method, capability
)
value = SecurityProfileSettings()
value.security_profile = super_value.security_profile
return value
class SecurityProfile(features.SecurityProfile):
_security_profile_mapping = {
SecurityProfileType.Standard: "",
SecurityProfileType.CVM: "ConfidentialVM",
}
def _initialize(self, *args: Any, **kwargs: Any) -> None:
super()._initialize(*args, **kwargs)
@classmethod
def settings_type(cls) -> Type[schema.FeatureSettings]:
return SecurityProfileSettings
@classmethod
def on_before_deployment(cls, *args: Any, **kwargs: Any) -> None:
environment = cast(Environment, kwargs.get("environment"))
security_profile = [kwargs.get("settings")]
for node in environment.nodes._list:
if security_profile:
settings = security_profile[0]
assert isinstance(settings, SecurityProfileSettings)
assert isinstance(settings.security_profile, SecurityProfileType)
node_context = get_node_context(node)
node_context.guest_vm_type = cls._security_profile_mapping[
settings.security_profile
]

Просмотреть файл

@ -20,7 +20,7 @@ import libvirt # type: ignore
import pycdlib # type: ignore import pycdlib # type: ignore
import yaml import yaml
from lisa import schema, search_space from lisa import feature, schema, search_space
from lisa.environment import Environment from lisa.environment import Environment
from lisa.feature import Feature from lisa.feature import Feature
from lisa.node import Node, RemoteNode, local_node_connect from lisa.node import Node, RemoteNode, local_node_connect
@ -42,7 +42,12 @@ from lisa.tools import (
Uname, Uname,
Whoami, Whoami,
) )
from lisa.util import LisaException, constants, get_public_key_data from lisa.util import (
LisaException,
NotMeetRequirementException,
constants,
get_public_key_data,
)
from lisa.util.logger import Logger, filter_ansi_escape, get_logger from lisa.util.logger import Logger, filter_ansi_escape, get_logger
from . import libvirt_events_thread from . import libvirt_events_thread
@ -54,6 +59,7 @@ from .context import (
get_environment_context, get_environment_context,
get_node_context, get_node_context,
) )
from .features import SecurityProfile, SecurityProfileSettings
from .platform_interface import IBaseLibvirtPlatform from .platform_interface import IBaseLibvirtPlatform
from .schema import ( from .schema import (
FIRMWARE_TYPE_BIOS, FIRMWARE_TYPE_BIOS,
@ -89,6 +95,7 @@ class BaseLibvirtPlatform(Platform, IBaseLibvirtPlatform):
_supported_features: List[Type[Feature]] = [ _supported_features: List[Type[Feature]] = [
SerialConsole, SerialConsole,
StartStop, StartStop,
SecurityProfile,
] ]
def __init__(self, runbook: schema.Platform) -> None: def __init__(self, runbook: schema.Platform) -> None:
@ -193,6 +200,36 @@ class BaseLibvirtPlatform(Platform, IBaseLibvirtPlatform):
self._configure_environment(environment, log) self._configure_environment(environment, log)
if environment.runbook.nodes_requirement:
for node_space in environment.runbook.nodes_requirement:
new_settings = search_space.SetSpace[schema.FeatureSettings](
is_allow_set=True
)
if node_space.features:
for current_settings in node_space.features.items:
# reload to type specified settings
try:
settings_type = feature.get_feature_settings_type_by_name(
current_settings.type,
BaseLibvirtPlatform.supported_features(),
)
except NotMeetRequirementException as identifier:
raise LisaException(
f"platform doesn't support all features. {identifier}"
)
new_setting = schema.load_by_type(
settings_type, current_settings
)
existing_setting = feature.get_feature_settings_by_name(
new_setting.type, new_settings, True
)
if existing_setting:
new_settings.remove(existing_setting)
new_setting = existing_setting.intersect(new_setting)
new_settings.add(new_setting)
node_space.features = new_settings
return self._configure_node_capabilities(environment, log) return self._configure_node_capabilities(environment, log)
def _deploy_environment(self, environment: Environment, log: Logger) -> None: def _deploy_environment(self, environment: Environment, log: Logger) -> None:
@ -312,10 +349,12 @@ class BaseLibvirtPlatform(Platform, IBaseLibvirtPlatform):
node_capabilities.network_interface.max_nic_count = 1 node_capabilities.network_interface.max_nic_count = 1
node_capabilities.network_interface.nic_count = 1 node_capabilities.network_interface.nic_count = 1
node_capabilities.gpu_count = 0 node_capabilities.gpu_count = 0
security_profile_setting = SecurityProfileSettings()
node_capabilities.features = search_space.SetSpace[schema.FeatureSettings]( node_capabilities.features = search_space.SetSpace[schema.FeatureSettings](
is_allow_set=True, is_allow_set=True,
items=[ items=[
schema.FeatureSettings.create(SerialConsole.name()), schema.FeatureSettings.create(SerialConsole.name()),
security_profile_setting,
], ],
) )
@ -564,6 +603,31 @@ class BaseLibvirtPlatform(Platform, IBaseLibvirtPlatform):
log: Logger, log: Logger,
) -> None: ) -> None:
self.host_node.shell.mkdir(Path(self.vm_disks_dir), exist_ok=True) self.host_node.shell.mkdir(Path(self.vm_disks_dir), exist_ok=True)
features_settings: Dict[str, schema.FeatureSettings] = {}
# collect all the features to handle special deployment logic. If one
# node has this, it needs to run.
nodes_requirement = environment.runbook.nodes_requirement
if nodes_requirement:
for node_space in nodes_requirement:
if not node_space.features:
continue
for feature_setting in node_space.features:
if feature_setting.type not in features_settings:
features_settings[feature_setting.type] = feature_setting
# change deployment for each feature.
for feature_type, setting in [
(t, s)
for t in self.supported_features()
for s in features_settings.values()
if t.name() == s.type
]:
feature_type.on_before_deployment(
environment=environment,
log=log,
settings=setting,
)
for node in environment.nodes.list(): for node in environment.nodes.list():
node_context = get_node_context(node) node_context = get_node_context(node)

Просмотреть файл

@ -122,6 +122,8 @@ SECURITY_PROFILE_BOOT = "secureboot"
SECURITY_PROFILE_CVM = "cvm" SECURITY_PROFILE_CVM = "cvm"
SECURITY_PROFILE_STATELESS = "stateless" SECURITY_PROFILE_STATELESS = "stateless"
GUEST_VM_TYPE_STANDARD = "STANDARD"
GUEST_VM_TYPE_CVM = "CVM"
PLATFORM = "platform" PLATFORM = "platform"
PLATFORM_READY = "ready" PLATFORM_READY = "ready"
PLATFORM_BAREMETAL = "baremetal" PLATFORM_BAREMETAL = "baremetal"