""" \author Tristan Israël """
from typing import List
from enum import Enum
import copy
[docs]
class DomainType(Enum):
""" This enumeration defines a Domain"s type """
UNKNOWN = 0
CORE = 1
BUSINESS = 2
[docs]
class Domain:
""" This class encapsulates information about a Domain """
id = 0
name = "NoName"
vcpu_group = "group1"
memory = 1000
vcpus = 1
cpu_affinity = [] # List of CPU pins
package = ""
domain_type = DomainType.BUSINESS
temp_disk_size = 0
def __init__(self, domain_name:str, domain_type:DomainType):
self.name = domain_name
self.domain_type = domain_type
[docs]
class Screen:
""" This class encapsulates information about a screen """
width = 0
height = 0
rotation = 0
class Gui:
""" This class encapsulates information about the GUI of a product """
use = False
app_package = ""
memory = 1000
class Pci:
""" This class encapsulates information about the PCI buses of a system """
blacklist = []
[docs]
class Topology:
""" This class encapsulates and handles information about the topology of a product
The topology is usually defined in the file /etc/safecor/topology.json
The topology object corresponds to the configuration that should be applied
to the device.
"""
domains = List[Domain]
product_name = "No Name"
use_usb = False
use_gui = False
uuid = ""
gui: Gui
screen: Screen
configurations = []
pci: Pci
languages = []
default_language = "en"
[docs]
def __init__(self, other=None):
""" Create a new Topology from scratch or as a deep copy if other is not None """
if other is None:
self.domains = []
self.gui = Gui()
self.screen = Screen()
self.pci = Pci()
self.__colors = {}
self.__initialized = False
else:
self.domains = copy.deepcopy(other.domains)
self.product_name = copy.deepcopy(other.product_name)
self.use_gui = copy.deepcopy(other.use_gui)
self.use_usb = copy.deepcopy(other.use_usb)
self.uuid = copy.deepcopy(other.uuid)
self.gui = copy.deepcopy(other.gui)
self.screen = copy.deepcopy(other.screen)
self.configurations = copy.deepcopy(other.configurations)
self.pci = copy.deepcopy(other.pci)
self.languages = copy.deepcopy(other.languages)
self.default_language = copy.deepcopy(other.default_language)
[docs]
def initialized(self) -> bool:
""" Returns whether the object is initialized """
return self.__initialized
[docs]
def set_initialized(self, initialized:bool):
""" Sets the objet initialized """
self.__initialized = initialized
[docs]
def colors(self) -> dict:
""" Returns the RGBA colors list as a list of 8 bit tuples (r, g, b, a)
.. seealso::
:func:`colors_as_hex`
"""
vals = {}
for name, color in self.__colors.items():
vals[name] = self.color_as_rgba(color)
return vals
[docs]
def colors_as_hex(self) -> dict:
""" Returns the colors list as hexadecimal values (#rrggbbaa)
.. seealso::
:func:`colors`
"""
colors = []
for color in self.__colors:
colors.append(self.color_as_hex(color))
return colors
[docs]
def color_as_hex(self, color_name:str) -> str:
""" Returns a named color as an hex value """
color = self.__colors.get(color_name, (0,0,0,0))
return self.__rgba_to_hex(color)
[docs]
def color_as_rgba(self, color_name:str) -> tuple[int, int, int, int]:
""" Returns an RGBA named color as a tuple value """
return self.__colors.get(color_name, (0,0,0,0))
[docs]
def add_color(self, color_name:str, color_value_as_hex:str):
""" Adds a named color to the list """
self.__colors[color_name] = self.__hex_to_rgba(color_value_as_hex)
def __hex_to_rgba(self, hex_color: str) -> tuple[int, int, int, int]:
""" Converts a color from hex to rgba tuple """
hex_color = hex_color.lstrip("#")
r = 0
g = 0
b = 0
a = 0
if len(hex_color) == 3:
r = int(hex_color[0], 16) << 4 | int(hex_color[0], 16)
g = int(hex_color[1], 16) << 4 | int(hex_color[1], 16)
b = int(hex_color[2], 16) << 4 | int(hex_color[2], 16)
a = 255
elif len(hex_color) == 4:
r = int(hex_color[0], 16) << 4 | int(hex_color[0], 16)
g = int(hex_color[1], 16) << 4 | int(hex_color[1], 16)
b = int(hex_color[2], 16) << 4 | int(hex_color[2], 16)
a = int(hex_color[3], 16) << 4 | int(hex_color[3], 16)
elif len(hex_color) == 6:
r = int(hex_color[0:2], 16)
g = int(hex_color[2:4], 16)
b = int(hex_color[4:6], 16)
a = 255
elif len(hex_color) == 8:
r = int(hex_color[0:2], 16)
g = int(hex_color[2:4], 16)
b = int(hex_color[4:6], 16)
a = int(hex_color[6:8], 16)
return (r,g,b,a)
def __rgba_to_hex(self, color_as_rgba:tuple[int, int, int, int]) -> str:
r = color_as_rgba[0]
g = color_as_rgba[1]
b = color_as_rgba[2]
a = color_as_rgba[3]
return f"#{r:0{2}x}{g:0{2}x}{b:0{2}x}{a:0{2}x}"
[docs]
def add_domain(self, domain:Domain):
""" Adds a Domain's definition to the list """
self.domains.append(domain)
[docs]
def domain_names(self) -> list:
""" Returns the list of Domain names """
return [d.name for d in self.domains]
[docs]
def domain(self, domain_name:str) -> Domain|None:
""" Returns the Domain object with the specified name """
if domain_name in self.domain_names():
result = [d for d in self.domains if d.name == domain_name]
if len(result) > 0:
return result[0]
return None
[docs]
def business_domains(self) -> list[Domain]:
""" Returns only the business domains """
doms = []
for dom in self.domains:
if dom.domain_type == DomainType.BUSINESS:
doms.append(dom)
return doms
[docs]
def is_pci_bus_blacklisted(self, bus_bdf:str) -> False:
""" Returns true if the bus is in the blacklist """
for d in self.pci.blacklist:
if bus_bdf.endswith(d):
return True
return False