various improvements
This commit is contained in:
		@@ -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()
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user