python-compute/node_agent/vm/installer.py

95 lines
2.8 KiB
Python
Raw Normal View History

2023-08-27 23:42:56 +03:00
import re
import libvirt
from ..utils.xml import Constructor
from ..utils.mac import random_mac
from .hardware import DomainCapabilities, vCPUMode, vCPUTopology, Boot
class vCPUInfo:
pass
class ImageVolume:
pass
class CloudInitConfig:
pass
class BootOrder:
pass
class VirtualMachineInstaller:
def __init__(self, session: libvirt.virConnect):
self.session = session
self.info = {}
def install(
self,
name: str | None = None,
title: str | None = None,
description: str = '',
os: str | None = None,
image: ImageVolume | None = None,
volumes: list['VolumeInfo'] | None = None,
vcpus: int = 0,
vcpu_info: vCPUInfo | None = None,
vcpu_mode: vCPUMode | None = None,
vcpu_topology: vCPUTopology | None = None,
memory: int = 0,
boot: Boot = Boot.BIOS,
boot_menu: bool = False,
boot_order: BootOrder = ('cdrom', 'hd'),
cloud_init: CloudInitConfig | None = None):
"""
Install virtual machine with passed parameters.
"""
domcaps = DomainCapabilities(self.session.session)
name = self._validate_name(name)
if vcpu_topology is None:
vcpu_topology = vCPUTopology(
{'sockets': 1, 'cores': vcpus, 'threads': 1})
self._validate_topology(vcpus, vcpu_topology)
if vcpu_info is None:
if not vcpu_mode:
vcpu_mode = vCPUMode.CUSTOM.value
xml_cpu = domcaps.best_cpu(vcpu_mode)
else:
raise NotImplementedError('Custom CPU not implemented')
xml_domain = Constructor().gen_domain_xml(
name=name,
title=title if title else name,
desc=description if description else '',
vcpus=vcpus,
memory=memory,
domain_type='hvm',
machine=domcaps.machine,
arch=domcaps.arch,
boot_order=('cdrom', 'hd'),
cpu=xml_cpu,
mac=random_mac()
)
return xml_domain
def _validate_name(self, name):
if name is None:
raise ValueError("'name' cannot be empty")
if isinstance(name, str):
if not re.match(r"^[a-z0-9_]+$", name, re.I):
raise ValueError(
"'name' can contain only letters, numbers "
"and underscore.")
return name.lower()
raise TypeError(f"'name' must be 'str', not {type(name)}")
def _validate_topology(self, vcpus, topology):
sockets = topology['sockets']
cores = topology['cores']
threads = topology['threads']
if sockets * cores * threads == vcpus:
return
raise ValueError("CPU topology must match the number of 'vcpus'")
def _define(self, xml: str):
self.session.defineXML(xml)