2023-11-23 02:34:02 +03:00
|
|
|
# This file is part of Compute
|
|
|
|
#
|
|
|
|
# Compute is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# Ansible is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2023-11-06 12:52:19 +03:00
|
|
|
"""Compute instance related objects schemas."""
|
|
|
|
|
|
|
|
import re
|
|
|
|
from enum import StrEnum
|
|
|
|
from pathlib import Path
|
|
|
|
|
2023-11-09 01:17:50 +03:00
|
|
|
from pydantic import BaseModel, Extra, validator
|
2023-11-06 12:52:19 +03:00
|
|
|
|
|
|
|
from compute.utils.units import DataUnit
|
|
|
|
|
|
|
|
|
2023-11-09 01:17:50 +03:00
|
|
|
class EntityModel(BaseModel):
|
|
|
|
"""Basic entity model."""
|
|
|
|
|
|
|
|
class Config:
|
|
|
|
"""Do not allow extra fields."""
|
|
|
|
|
|
|
|
extra = Extra.forbid
|
|
|
|
|
|
|
|
|
2023-11-06 12:52:19 +03:00
|
|
|
class CPUEmulationMode(StrEnum):
|
|
|
|
"""CPU emulation mode enumerated."""
|
|
|
|
|
|
|
|
HOST_PASSTHROUGH = 'host-passthrough'
|
|
|
|
HOST_MODEL = 'host-model'
|
|
|
|
CUSTOM = 'custom'
|
|
|
|
MAXIMUM = 'maximum'
|
|
|
|
|
|
|
|
|
2023-11-09 01:17:50 +03:00
|
|
|
class CPUTopologySchema(EntityModel):
|
2023-11-06 12:52:19 +03:00
|
|
|
"""CPU topology model."""
|
|
|
|
|
|
|
|
sockets: int
|
|
|
|
cores: int
|
|
|
|
threads: int
|
|
|
|
dies: int = 1
|
|
|
|
|
|
|
|
|
2023-11-09 01:17:50 +03:00
|
|
|
class CPUFeaturesSchema(EntityModel):
|
2023-11-06 12:52:19 +03:00
|
|
|
"""CPU features model."""
|
|
|
|
|
|
|
|
require: list[str]
|
|
|
|
disable: list[str]
|
|
|
|
|
|
|
|
|
2023-11-09 01:17:50 +03:00
|
|
|
class CPUSchema(EntityModel):
|
2023-11-06 12:52:19 +03:00
|
|
|
"""CPU model."""
|
|
|
|
|
|
|
|
emulation_mode: CPUEmulationMode
|
2023-11-09 01:17:50 +03:00
|
|
|
model: str | None
|
|
|
|
vendor: str | None
|
|
|
|
topology: CPUTopologySchema | None
|
|
|
|
features: CPUFeaturesSchema | None
|
2023-11-06 12:52:19 +03:00
|
|
|
|
|
|
|
|
2023-11-06 17:47:56 +03:00
|
|
|
class VolumeType(StrEnum):
|
2023-11-06 12:52:19 +03:00
|
|
|
"""Storage volume types enumeration."""
|
|
|
|
|
|
|
|
FILE = 'file'
|
|
|
|
|
|
|
|
|
2023-11-09 01:17:50 +03:00
|
|
|
class VolumeCapacitySchema(EntityModel):
|
2023-11-06 12:52:19 +03:00
|
|
|
"""Storage volume capacity field model."""
|
|
|
|
|
|
|
|
value: int
|
|
|
|
unit: DataUnit
|
|
|
|
|
|
|
|
|
2023-11-09 01:17:50 +03:00
|
|
|
class VolumeSchema(EntityModel):
|
2023-11-06 12:52:19 +03:00
|
|
|
"""Storage volume model."""
|
|
|
|
|
2023-11-06 17:47:56 +03:00
|
|
|
type: VolumeType # noqa: A003
|
2023-11-06 12:52:19 +03:00
|
|
|
target: str
|
2023-11-06 17:47:56 +03:00
|
|
|
capacity: VolumeCapacitySchema
|
2023-11-09 01:17:50 +03:00
|
|
|
source: str | None = None
|
|
|
|
is_readonly: bool = False
|
2023-11-06 12:52:19 +03:00
|
|
|
is_system: bool = False
|
|
|
|
|
|
|
|
|
2023-11-09 01:17:50 +03:00
|
|
|
class NetworkInterfaceSchema(EntityModel):
|
2023-11-06 12:52:19 +03:00
|
|
|
"""Network inerface model."""
|
|
|
|
|
|
|
|
source: str
|
|
|
|
mac: str
|
|
|
|
|
|
|
|
|
2023-11-09 01:17:50 +03:00
|
|
|
class BootOptionsSchema(EntityModel):
|
2023-11-06 12:52:19 +03:00
|
|
|
"""Instance boot settings."""
|
|
|
|
|
|
|
|
order: tuple
|
|
|
|
|
|
|
|
|
2023-11-09 01:17:50 +03:00
|
|
|
class InstanceSchema(EntityModel):
|
2023-11-06 12:52:19 +03:00
|
|
|
"""Compute instance model."""
|
|
|
|
|
|
|
|
name: str
|
2023-11-09 01:17:50 +03:00
|
|
|
title: str | None
|
|
|
|
description: str | None
|
2023-11-06 12:52:19 +03:00
|
|
|
memory: int
|
|
|
|
max_memory: int
|
|
|
|
vcpus: int
|
|
|
|
max_vcpus: int
|
|
|
|
cpu: CPUSchema
|
|
|
|
machine: str
|
|
|
|
emulator: Path
|
|
|
|
arch: str
|
|
|
|
boot: BootOptionsSchema
|
2023-11-06 17:47:56 +03:00
|
|
|
volumes: list[VolumeSchema]
|
2023-11-06 12:52:19 +03:00
|
|
|
network_interfaces: list[NetworkInterfaceSchema]
|
2023-11-09 01:17:50 +03:00
|
|
|
image: str | None = None
|
2023-11-06 12:52:19 +03:00
|
|
|
|
|
|
|
@validator('name')
|
|
|
|
def _check_name(cls, value: str) -> str: # noqa: N805
|
|
|
|
if not re.match(r'^[a-z0-9_]+$', value):
|
|
|
|
msg = (
|
|
|
|
'Name can contain only lowercase letters, numbers '
|
|
|
|
'and underscore.'
|
|
|
|
)
|
|
|
|
raise ValueError(msg)
|
|
|
|
return value
|
|
|
|
|
2023-11-09 01:17:50 +03:00
|
|
|
@validator('cpu')
|
|
|
|
def _check_topology(cls, cpu: int, values: dict) -> CPUSchema: # noqa: N805
|
|
|
|
topo = cpu.topology
|
|
|
|
max_vcpus = values['max_vcpus']
|
|
|
|
if topo and topo.sockets * topo.cores * topo.threads != max_vcpus:
|
|
|
|
msg = f'CPU topology does not match with {max_vcpus=}'
|
|
|
|
raise ValueError(msg)
|
|
|
|
return cpu
|
|
|
|
|
2023-11-06 12:52:19 +03:00
|
|
|
@validator('volumes')
|
2023-11-09 01:17:50 +03:00
|
|
|
def _check_volumes(cls, volumes: list) -> list: # noqa: N805
|
|
|
|
if len([v for v in volumes if v.is_system is True]) != 1:
|
|
|
|
msg = 'volumes list must contain one system volume'
|
2023-11-06 12:52:19 +03:00
|
|
|
raise ValueError(msg)
|
2023-11-09 01:17:50 +03:00
|
|
|
vol_with_source = 0
|
|
|
|
for vol in volumes:
|
|
|
|
if vol.is_system is True and vol.is_readonly is True:
|
|
|
|
msg = 'volume marked as system cannot be readonly'
|
|
|
|
raise ValueError(msg)
|
|
|
|
if vol.source is not None:
|
|
|
|
vol_with_source += 1
|
|
|
|
return volumes
|
2023-11-06 12:52:19 +03:00
|
|
|
|
|
|
|
@validator('network_interfaces')
|
|
|
|
def _check_network_interfaces(cls, value: list) -> list: # noqa: N805
|
|
|
|
if not value:
|
|
|
|
msg = 'Network interfaces list must contain at least one element'
|
|
|
|
raise ValueError(msg)
|
|
|
|
return value
|