diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/conf_mode/container.py | 9 | ||||
-rwxr-xr-x | src/services/vyos-http-api-server | 46 |
2 files changed, 38 insertions, 17 deletions
diff --git a/src/conf_mode/container.py b/src/conf_mode/container.py index 91a10e891..ca09dff9f 100755 --- a/src/conf_mode/container.py +++ b/src/conf_mode/container.py @@ -16,6 +16,7 @@ import os +from decimal import Decimal from hashlib import sha256 from ipaddress import ip_address from ipaddress import ip_network @@ -127,6 +128,11 @@ def verify(container): f'locally. Please use "add container image {image}" to add it '\ f'to the system! Container "{name}" will not be started!') + if 'cpu_quota' in container_config: + cores = vyos.cpu.get_core_count() + if Decimal(container_config['cpu_quota']) > cores: + raise ConfigError(f'Cannot set limit to more cores than available "{name}"!') + if 'network' in container_config: if len(container_config['network']) > 1: raise ConfigError(f'Only one network can be specified for container "{name}"!') @@ -257,6 +263,7 @@ def verify(container): def generate_run_arguments(name, container_config): image = container_config['image'] + cpu_quota = container_config['cpu_quota'] memory = container_config['memory'] shared_memory = container_config['shared_memory'] restart = container_config['restart'] @@ -333,7 +340,7 @@ def generate_run_arguments(name, container_config): if 'allow_host_pid' in container_config: host_pid = '--pid host' - container_base_cmd = f'--detach --interactive --tty --replace {capabilities} ' \ + container_base_cmd = f'--detach --interactive --tty --replace {capabilities} --cpus {cpu_quota} ' \ f'--memory {memory}m --shm-size {shared_memory}m --memory-swap 0 --restart {restart} ' \ f'--name {name} {hostname} {device} {port} {volume} {env_opt} {label} {uid} {host_pid}' diff --git a/src/services/vyos-http-api-server b/src/services/vyos-http-api-server index ecbf6fcf9..7f5233c6b 100755 --- a/src/services/vyos-http-api-server +++ b/src/services/vyos-http-api-server @@ -23,16 +23,17 @@ import logging import signal import traceback import threading +from enum import Enum from time import sleep -from typing import List, Union, Callable, Dict +from typing import List, Union, Callable, Dict, Self from fastapi import FastAPI, Depends, Request, Response, HTTPException from fastapi import BackgroundTasks from fastapi.responses import HTMLResponse from fastapi.exceptions import RequestValidationError from fastapi.routing import APIRoute -from pydantic import BaseModel, StrictStr, validator +from pydantic import BaseModel, StrictStr, validator, model_validator from starlette.middleware.cors import CORSMiddleware from starlette.datastructures import FormData from starlette.formparsers import FormParser, MultiPartParser @@ -177,16 +178,35 @@ class ConfigFileModel(ApiModel): } } + +class ImageOp(str, Enum): + add = "add" + delete = "delete" + show = "show" + set_default = "set_default" + + class ImageModel(ApiModel): - op: StrictStr + op: ImageOp url: StrictStr = None name: StrictStr = None + @model_validator(mode='after') + def check_data(self) -> Self: + if self.op == 'add': + if not self.url: + raise ValueError("Missing required field \"url\"") + elif self.op in ['delete', 'set_default']: + if not self.name: + raise ValueError("Missing required field \"name\"") + + return self + class Config: schema_extra = { "example": { "key": "id_key", - "op": "add | delete", + "op": "add | delete | show | set_default", "url": "imagelocation", "name": "imagename", } @@ -668,19 +688,13 @@ def image_op(data: ImageModel): try: if op == 'add': - if data.url: - url = data.url - else: - return error(400, "Missing required field \"url\"") - res = session.install_image(url) + res = session.install_image(data.url) elif op == 'delete': - if data.name: - name = data.name - else: - return error(400, "Missing required field \"name\"") - res = session.remove_image(name) - else: - return error(400, f"'{op}' is not a valid operation") + res = session.remove_image(data.name) + elif op == 'show': + res = session.show(["system", "image"]) + elif op == 'set_default': + res = session.set_default_image(data.name) except ConfigSessionError as e: return error(400, str(e)) except Exception as e: |