various improvements
This commit is contained in:
		@@ -1,6 +1,21 @@
 | 
			
		||||
# 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/>.
 | 
			
		||||
 | 
			
		||||
"""Compute instances management library."""
 | 
			
		||||
 | 
			
		||||
__version__ = '0.1.0'
 | 
			
		||||
__version__ = '0.1.0-dev1'
 | 
			
		||||
 | 
			
		||||
from .instance import Instance, InstanceConfig, InstanceSchema
 | 
			
		||||
from .session import Session
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,21 @@
 | 
			
		||||
# 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/>.
 | 
			
		||||
 | 
			
		||||
"""Command line interface for compute module."""
 | 
			
		||||
 | 
			
		||||
from compute.cli import control
 | 
			
		||||
from compute.cli import main
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
control.cli()
 | 
			
		||||
main.cli()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,18 @@
 | 
			
		||||
# 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/>.
 | 
			
		||||
 | 
			
		||||
"""Command line interface."""
 | 
			
		||||
 | 
			
		||||
import argparse
 | 
			
		||||
@@ -15,10 +30,7 @@ import yaml
 | 
			
		||||
from pydantic import ValidationError
 | 
			
		||||
 | 
			
		||||
from compute import __version__
 | 
			
		||||
from compute.exceptions import (
 | 
			
		||||
    ComputeServiceError,
 | 
			
		||||
    GuestAgentTimeoutExceededError,
 | 
			
		||||
)
 | 
			
		||||
from compute.exceptions import ComputeError, GuestAgentTimeoutExceededError
 | 
			
		||||
from compute.instance import GuestAgent
 | 
			
		||||
from compute.session import Session
 | 
			
		||||
from compute.utils import ids
 | 
			
		||||
@@ -198,10 +210,23 @@ def _create_instance(session: Session, file: io.TextIOWrapper) -> None:
 | 
			
		||||
        sys.exit()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _shutdown_instance(session: Session, args: argparse.Namespace) -> None:
 | 
			
		||||
    instance = session.get_instance(args.instance)
 | 
			
		||||
    if args.soft:
 | 
			
		||||
        method = 'SOFT'
 | 
			
		||||
    elif args.hard:
 | 
			
		||||
        method = 'HARD'
 | 
			
		||||
    elif args.unsafe:
 | 
			
		||||
        method = 'UNSAFE'
 | 
			
		||||
    else:
 | 
			
		||||
        method = 'NORMAL'
 | 
			
		||||
    instance.shutdown(method)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main(session: Session, args: argparse.Namespace) -> None:
 | 
			
		||||
    """Perform actions."""
 | 
			
		||||
    match args.command:
 | 
			
		||||
        case 'create':
 | 
			
		||||
        case 'init':
 | 
			
		||||
            _create_instance(session, args.file)
 | 
			
		||||
        case 'exec':
 | 
			
		||||
            _exec_guest_agent_command(session, args)
 | 
			
		||||
@@ -211,14 +236,16 @@ def main(session: Session, args: argparse.Namespace) -> None:
 | 
			
		||||
            instance = session.get_instance(args.instance)
 | 
			
		||||
            instance.start()
 | 
			
		||||
        case 'shutdown':
 | 
			
		||||
            instance = session.get_instance(args.instance)
 | 
			
		||||
            instance.shutdown(args.method)
 | 
			
		||||
            _shutdown_instance(session, args)
 | 
			
		||||
        case 'reboot':
 | 
			
		||||
            instance = session.get_instance(args.instance)
 | 
			
		||||
            instance.reboot()
 | 
			
		||||
        case 'reset':
 | 
			
		||||
            instance = session.get_instance(args.instance)
 | 
			
		||||
            instance.reset()
 | 
			
		||||
        case 'powrst':
 | 
			
		||||
            instance = session.get_instance(args.instance)
 | 
			
		||||
            instance.power_reset()
 | 
			
		||||
        case 'pause':
 | 
			
		||||
            instance = session.get_instance(args.instance)
 | 
			
		||||
            instance.pause()
 | 
			
		||||
@@ -234,7 +261,7 @@ def main(session: Session, args: argparse.Namespace) -> None:
 | 
			
		||||
        case 'setmem':
 | 
			
		||||
            instance = session.get_instance(args.instance)
 | 
			
		||||
            instance.set_memory(args.memory, live=True)
 | 
			
		||||
        case 'setpasswd':
 | 
			
		||||
        case 'setpass':
 | 
			
		||||
            instance = session.get_instance(args.instance)
 | 
			
		||||
            instance.set_user_password(
 | 
			
		||||
                args.username,
 | 
			
		||||
@@ -261,7 +288,6 @@ def cli() -> None:  # noqa: PLR0915
 | 
			
		||||
        '-c',
 | 
			
		||||
        '--connect',
 | 
			
		||||
        metavar='URI',
 | 
			
		||||
        default='qemu:///system',
 | 
			
		||||
        help='libvirt connection URI',
 | 
			
		||||
    )
 | 
			
		||||
    root.add_argument(
 | 
			
		||||
@@ -270,7 +296,7 @@ def cli() -> None:  # noqa: PLR0915
 | 
			
		||||
        type=str.lower,
 | 
			
		||||
        metavar='LEVEL',
 | 
			
		||||
        choices=log_levels,
 | 
			
		||||
        help='log level [envvar: CMP_LOG]',
 | 
			
		||||
        help='log level',
 | 
			
		||||
    )
 | 
			
		||||
    root.add_argument(
 | 
			
		||||
        '-V',
 | 
			
		||||
@@ -280,13 +306,16 @@ def cli() -> None:  # noqa: PLR0915
 | 
			
		||||
    )
 | 
			
		||||
    subparsers = root.add_subparsers(dest='command', metavar='COMMAND')
 | 
			
		||||
 | 
			
		||||
    # create command
 | 
			
		||||
    create = subparsers.add_parser(
 | 
			
		||||
        'create', help='create new instance from YAML config file'
 | 
			
		||||
    # init command
 | 
			
		||||
    init = subparsers.add_parser(
 | 
			
		||||
        'init', help='initialise instance using YAML config file'
 | 
			
		||||
    )
 | 
			
		||||
    create.add_argument(
 | 
			
		||||
    init.add_argument(
 | 
			
		||||
        'file',
 | 
			
		||||
        type=argparse.FileType('r', encoding='UTF-8'),
 | 
			
		||||
        nargs='?',
 | 
			
		||||
        default='instance.yaml',
 | 
			
		||||
        help='instance config [default: instance.yaml]',
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    # exec subcommand
 | 
			
		||||
@@ -307,14 +336,14 @@ def cli() -> None:  # noqa: PLR0915
 | 
			
		||||
        default=60,
 | 
			
		||||
        help=(
 | 
			
		||||
            'waiting time in seconds for a command to be executed '
 | 
			
		||||
            'in guest, 60 sec by default'
 | 
			
		||||
            'in guest [default: 60]'
 | 
			
		||||
        ),
 | 
			
		||||
    )
 | 
			
		||||
    execute.add_argument(
 | 
			
		||||
        '-x',
 | 
			
		||||
        '--executable',
 | 
			
		||||
        default='/bin/sh',
 | 
			
		||||
        help='path to executable in guest, /bin/sh by default',
 | 
			
		||||
        help='path to executable in guest [default: /bin/sh]',
 | 
			
		||||
    )
 | 
			
		||||
    execute.add_argument(
 | 
			
		||||
        '-e',
 | 
			
		||||
@@ -352,12 +381,36 @@ def cli() -> None:  # noqa: PLR0915
 | 
			
		||||
    # shutdown subcommand
 | 
			
		||||
    shutdown = subparsers.add_parser('shutdown', help='shutdown instance')
 | 
			
		||||
    shutdown.add_argument('instance')
 | 
			
		||||
    shutdown.add_argument(
 | 
			
		||||
        '-m',
 | 
			
		||||
        '--method',
 | 
			
		||||
        choices=['soft', 'normal', 'hard', 'unsafe'],
 | 
			
		||||
        default='normal',
 | 
			
		||||
        help='use shutdown method',
 | 
			
		||||
    shutdown_opts = shutdown.add_mutually_exclusive_group()
 | 
			
		||||
    shutdown_opts.add_argument(
 | 
			
		||||
        '-s',
 | 
			
		||||
        '--soft',
 | 
			
		||||
        action='store_true',
 | 
			
		||||
        help='normal guest OS shutdown, guest agent is used',
 | 
			
		||||
    )
 | 
			
		||||
    shutdown_opts.add_argument(
 | 
			
		||||
        '-n',
 | 
			
		||||
        '--normal',
 | 
			
		||||
        action='store_true',
 | 
			
		||||
        help='shutdown with hypervisor selected method [default]',
 | 
			
		||||
    )
 | 
			
		||||
    shutdown_opts.add_argument(
 | 
			
		||||
        '-H',
 | 
			
		||||
        '--hard',
 | 
			
		||||
        action='store_true',
 | 
			
		||||
        help=(
 | 
			
		||||
            "gracefully destroy instance, it's like long "
 | 
			
		||||
            'pressing the power button'
 | 
			
		||||
        ),
 | 
			
		||||
    )
 | 
			
		||||
    shutdown_opts.add_argument(
 | 
			
		||||
        '-u',
 | 
			
		||||
        '--unsafe',
 | 
			
		||||
        action='store_true',
 | 
			
		||||
        help=(
 | 
			
		||||
            'destroy instance, this is similar to a power outage '
 | 
			
		||||
            'and may result in data loss or corruption'
 | 
			
		||||
        ),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    # reboot subcommand
 | 
			
		||||
@@ -368,6 +421,10 @@ def cli() -> None:  # noqa: PLR0915
 | 
			
		||||
    reset = subparsers.add_parser('reset', help='reset instance')
 | 
			
		||||
    reset.add_argument('instance')
 | 
			
		||||
 | 
			
		||||
    # powrst subcommand
 | 
			
		||||
    powrst = subparsers.add_parser('powrst', help='power reset instance')
 | 
			
		||||
    powrst.add_argument('instance')
 | 
			
		||||
 | 
			
		||||
    # pause subcommand
 | 
			
		||||
    pause = subparsers.add_parser('pause', help='pause instance')
 | 
			
		||||
    pause.add_argument('instance')
 | 
			
		||||
@@ -390,15 +447,15 @@ def cli() -> None:  # noqa: PLR0915
 | 
			
		||||
    setmem.add_argument('instance')
 | 
			
		||||
    setmem.add_argument('memory', type=int, help='memory in MiB')
 | 
			
		||||
 | 
			
		||||
    # setpasswd subcommand
 | 
			
		||||
    setpasswd = subparsers.add_parser(
 | 
			
		||||
        'setpasswd',
 | 
			
		||||
    # setpass subcommand
 | 
			
		||||
    setpass = subparsers.add_parser(
 | 
			
		||||
        'setpass',
 | 
			
		||||
        help='set user password in guest',
 | 
			
		||||
    )
 | 
			
		||||
    setpasswd.add_argument('instance')
 | 
			
		||||
    setpasswd.add_argument('username')
 | 
			
		||||
    setpasswd.add_argument('password')
 | 
			
		||||
    setpasswd.add_argument(
 | 
			
		||||
    setpass.add_argument('instance')
 | 
			
		||||
    setpass.add_argument('username')
 | 
			
		||||
    setpass.add_argument('password')
 | 
			
		||||
    setpass.add_argument(
 | 
			
		||||
        '-e',
 | 
			
		||||
        '--encrypted',
 | 
			
		||||
        action='store_true',
 | 
			
		||||
@@ -419,10 +476,18 @@ def cli() -> None:  # noqa: PLR0915
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    log.debug('CLI started with args: %s', args)
 | 
			
		||||
 | 
			
		||||
    connect_uri = (
 | 
			
		||||
        args.connect
 | 
			
		||||
        or os.getenv('CMP_LIBVIRT_URI')
 | 
			
		||||
        or os.getenv('LIBVIRT_DEFAULT_URI')
 | 
			
		||||
        or 'qemu:///system'
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        with Session(args.connect) as session:
 | 
			
		||||
        with Session(connect_uri) as session:
 | 
			
		||||
            main(session, args)
 | 
			
		||||
    except ComputeServiceError as e:
 | 
			
		||||
    except ComputeError as e:
 | 
			
		||||
        sys.exit(f'error: {e}')
 | 
			
		||||
    except KeyboardInterrupt:
 | 
			
		||||
        sys.exit()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										30
									
								
								compute/common.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								compute/common.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
# 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/>.
 | 
			
		||||
 | 
			
		||||
"""Common symbols."""
 | 
			
		||||
 | 
			
		||||
from abc import ABC, abstractmethod
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EntityConfig(ABC):
 | 
			
		||||
    """An abstract entity XML config builder class."""
 | 
			
		||||
 | 
			
		||||
    @abstractmethod
 | 
			
		||||
    def to_xml(self) -> str:
 | 
			
		||||
        """Return device XML config."""
 | 
			
		||||
        raise NotImplementedError
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DeviceConfig = EntityConfig
 | 
			
		||||
@@ -1,19 +1,34 @@
 | 
			
		||||
# 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/>.
 | 
			
		||||
 | 
			
		||||
"""Exceptions."""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ComputeServiceError(Exception):
 | 
			
		||||
    """Basic exception class for Compute."""
 | 
			
		||||
class ComputeError(Exception):
 | 
			
		||||
    """Basic exception class."""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ConfigLoaderError(ComputeServiceError):
 | 
			
		||||
class ConfigLoaderError(ComputeError):
 | 
			
		||||
    """Something went wrong when loading configuration."""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SessionError(ComputeServiceError):
 | 
			
		||||
class SessionError(ComputeError):
 | 
			
		||||
    """Something went wrong while connecting to libvirtd."""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GuestAgentError(ComputeServiceError):
 | 
			
		||||
class GuestAgentError(ComputeError):
 | 
			
		||||
    """Something went wring when QEMU Guest Agent call."""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -33,7 +48,7 @@ class GuestAgentCommandNotSupportedError(GuestAgentError):
 | 
			
		||||
    """Guest agent command is not supported or blacklisted on guest."""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class StoragePoolError(ComputeServiceError):
 | 
			
		||||
class StoragePoolError(ComputeError):
 | 
			
		||||
    """Something went wrong when operating with storage pool."""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -53,7 +68,7 @@ class VolumeNotFoundError(StoragePoolError):
 | 
			
		||||
        super().__init__(f"storage volume '{msg}' not found")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InstanceError(ComputeServiceError):
 | 
			
		||||
class InstanceError(ComputeError):
 | 
			
		||||
    """Something went wrong while interacting with the domain."""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,18 @@
 | 
			
		||||
# 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/>.
 | 
			
		||||
 | 
			
		||||
from .guest_agent import GuestAgent
 | 
			
		||||
from .instance import Instance, InstanceConfig
 | 
			
		||||
from .schemas import InstanceSchema
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,18 @@
 | 
			
		||||
# 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/>.
 | 
			
		||||
 | 
			
		||||
"""Interacting with the QEMU Guest Agent."""
 | 
			
		||||
 | 
			
		||||
import json
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,18 @@
 | 
			
		||||
# 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/>.
 | 
			
		||||
 | 
			
		||||
"""Manage compute instances."""
 | 
			
		||||
 | 
			
		||||
__all__ = ['Instance', 'InstanceConfig', 'InstanceInfo']
 | 
			
		||||
@@ -9,6 +24,7 @@ import libvirt
 | 
			
		||||
from lxml import etree
 | 
			
		||||
from lxml.builder import E
 | 
			
		||||
 | 
			
		||||
from compute.common import DeviceConfig, EntityConfig
 | 
			
		||||
from compute.exceptions import (
 | 
			
		||||
    GuestAgentCommandNotSupportedError,
 | 
			
		||||
    InstanceError,
 | 
			
		||||
@@ -28,8 +44,8 @@ from .schemas import (
 | 
			
		||||
log = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InstanceConfig:
 | 
			
		||||
    """Compute instance config builder."""
 | 
			
		||||
class InstanceConfig(EntityConfig):
 | 
			
		||||
    """Compute instance XML config builder."""
 | 
			
		||||
 | 
			
		||||
    def __init__(self, schema: InstanceSchema):
 | 
			
		||||
        """
 | 
			
		||||
@@ -181,10 +197,6 @@ class InstanceInfo(NamedTuple):
 | 
			
		||||
    cputime: int
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DeviceConfig:
 | 
			
		||||
    """Abstract device config class."""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Instance:
 | 
			
		||||
    """Manage compute instances."""
 | 
			
		||||
 | 
			
		||||
@@ -492,7 +504,7 @@ class Instance:
 | 
			
		||||
        return child[0].getparent() if child else None
 | 
			
		||||
 | 
			
		||||
    def attach_device(
 | 
			
		||||
        self, device: 'DeviceConfig', *, live: bool = False
 | 
			
		||||
        self, device: DeviceConfig, *, live: bool = False
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Attach device to compute instance.
 | 
			
		||||
@@ -517,7 +529,7 @@ class Instance:
 | 
			
		||||
        self.domain.attachDeviceFlags(device.to_xml(), flags=flags)
 | 
			
		||||
 | 
			
		||||
    def detach_device(
 | 
			
		||||
        self, device: 'DeviceConfig', *, live: bool = False
 | 
			
		||||
        self, device: DeviceConfig, *, live: bool = False
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Dettach device from compute instance.
 | 
			
		||||
@@ -545,8 +557,8 @@ class Instance:
 | 
			
		||||
        """
 | 
			
		||||
        Detach disk device by target name.
 | 
			
		||||
 | 
			
		||||
        There is no ``attach_disk()`` method. Use :method:`attach_device`
 | 
			
		||||
        with :class:`DiskConfig` as parameter.
 | 
			
		||||
        There is no ``attach_disk()`` method. Use :func:`attach_device`
 | 
			
		||||
        with :class:`DiskConfig` as argument.
 | 
			
		||||
 | 
			
		||||
        :param name: Disk name e.g. 'vda', 'sda', etc. This name may
 | 
			
		||||
            not match the name of the disk inside the guest OS.
 | 
			
		||||
@@ -574,14 +586,14 @@ class Instance:
 | 
			
		||||
                raise InstanceError(msg)
 | 
			
		||||
        self.detach_device(DiskConfig(**disk_params), live=True)
 | 
			
		||||
 | 
			
		||||
    def resize_volume(
 | 
			
		||||
    def resize_disk(
 | 
			
		||||
        self, name: str, capacity: int, unit: units.DataUnit
 | 
			
		||||
    ) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Resize attached block device.
 | 
			
		||||
 | 
			
		||||
        :param name: Disk device name e.g. `vda`, `sda`, etc.
 | 
			
		||||
        :param capacity: New volume capacity.
 | 
			
		||||
        :param capacity: New capacity.
 | 
			
		||||
        :param unit: Capacity unit.
 | 
			
		||||
        """
 | 
			
		||||
        self.domain.blockResize(
 | 
			
		||||
@@ -590,6 +602,10 @@ class Instance:
 | 
			
		||||
            flags=libvirt.VIR_DOMAIN_BLOCK_RESIZE_BYTES,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def get_disks(self) -> list[DiskConfig]:
 | 
			
		||||
        """Return list of attached disks."""
 | 
			
		||||
        raise NotImplementedError
 | 
			
		||||
 | 
			
		||||
    def pause(self) -> None:
 | 
			
		||||
        """Pause instance."""
 | 
			
		||||
        if not self.is_running():
 | 
			
		||||
@@ -600,9 +616,9 @@ class Instance:
 | 
			
		||||
        """Resume paused instance."""
 | 
			
		||||
        self.domain.resume()
 | 
			
		||||
 | 
			
		||||
    def list_ssh_keys(self, user: str) -> list[str]:
 | 
			
		||||
    def get_ssh_keys(self, user: str) -> list[str]:
 | 
			
		||||
        """
 | 
			
		||||
        Get list of SSH keys on guest for specific user.
 | 
			
		||||
        Return list of SSH keys on guest for specific user.
 | 
			
		||||
 | 
			
		||||
        :param user: Username.
 | 
			
		||||
        """
 | 
			
		||||
@@ -617,7 +633,7 @@ class Instance:
 | 
			
		||||
        """
 | 
			
		||||
        raise NotImplementedError
 | 
			
		||||
 | 
			
		||||
    def remove_ssh_keys(self, user: str, ssh_keys: list[str]) -> None:
 | 
			
		||||
    def delete_ssh_keys(self, user: str, ssh_keys: list[str]) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Remove SSH keys from guest for specific user.
 | 
			
		||||
 | 
			
		||||
@@ -632,7 +648,7 @@ class Instance:
 | 
			
		||||
        """
 | 
			
		||||
        Set new user password in guest OS.
 | 
			
		||||
 | 
			
		||||
        This action performs by guest agent inside guest.
 | 
			
		||||
        This action performs by guest agent inside the guest.
 | 
			
		||||
 | 
			
		||||
        :param user: Username.
 | 
			
		||||
        :param password: Password.
 | 
			
		||||
@@ -653,6 +669,7 @@ class Instance:
 | 
			
		||||
        return self.domain.XMLDesc(flags)
 | 
			
		||||
 | 
			
		||||
    def delete(self) -> None:
 | 
			
		||||
        """Undefine instance and delete local volumes."""
 | 
			
		||||
        """Undefine instance."""
 | 
			
		||||
        # TODO @ge: delete local disks
 | 
			
		||||
        self.shutdown(method='HARD')
 | 
			
		||||
        self.domain.undefine()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,18 @@
 | 
			
		||||
# 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/>.
 | 
			
		||||
 | 
			
		||||
"""Compute instance related objects schemas."""
 | 
			
		||||
 | 
			
		||||
import re
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,18 @@
 | 
			
		||||
# 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/>.
 | 
			
		||||
 | 
			
		||||
"""Hypervisor session manager."""
 | 
			
		||||
 | 
			
		||||
import logging
 | 
			
		||||
 
 | 
			
		||||
@@ -1,2 +1,17 @@
 | 
			
		||||
# 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/>.
 | 
			
		||||
 | 
			
		||||
from .pool import StoragePool
 | 
			
		||||
from .volume import DiskConfig, Volume, VolumeConfig
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,18 @@
 | 
			
		||||
# 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/>.
 | 
			
		||||
 | 
			
		||||
"""Manage storage pools."""
 | 
			
		||||
 | 
			
		||||
import logging
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,18 @@
 | 
			
		||||
# 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/>.
 | 
			
		||||
 | 
			
		||||
"""Manage storage volumes."""
 | 
			
		||||
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
@@ -8,13 +23,14 @@ import libvirt
 | 
			
		||||
from lxml import etree
 | 
			
		||||
from lxml.builder import E
 | 
			
		||||
 | 
			
		||||
from compute.common import DeviceConfig, EntityConfig
 | 
			
		||||
from compute.utils import units
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@dataclass
 | 
			
		||||
class VolumeConfig:
 | 
			
		||||
class VolumeConfig(EntityConfig):
 | 
			
		||||
    """
 | 
			
		||||
    Storage volume config builder.
 | 
			
		||||
    Storage volume XML config builder.
 | 
			
		||||
 | 
			
		||||
    Generate XML config for creating a volume in a libvirt
 | 
			
		||||
    storage pool.
 | 
			
		||||
@@ -48,9 +64,9 @@ class VolumeConfig:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@dataclass
 | 
			
		||||
class DiskConfig:
 | 
			
		||||
class DiskConfig(DeviceConfig):
 | 
			
		||||
    """
 | 
			
		||||
    Disk config builder.
 | 
			
		||||
    Disk XML config builder.
 | 
			
		||||
 | 
			
		||||
    Generate XML config for attaching or detaching storage volumes
 | 
			
		||||
    to compute instances.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,18 @@
 | 
			
		||||
# 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/>.
 | 
			
		||||
 | 
			
		||||
"""Configuration loader."""
 | 
			
		||||
 | 
			
		||||
import tomllib
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,18 @@
 | 
			
		||||
# 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/>.
 | 
			
		||||
 | 
			
		||||
"""Random identificators."""
 | 
			
		||||
 | 
			
		||||
# ruff: noqa: S311, C417
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,18 @@
 | 
			
		||||
# 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/>.
 | 
			
		||||
 | 
			
		||||
"""Tools for data units convertion."""
 | 
			
		||||
 | 
			
		||||
from enum import StrEnum
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user