various improvements

This commit is contained in:
ge
2023-11-23 02:34:02 +03:00
parent b9d089dd78
commit 05f90b14f2
200 changed files with 15968 additions and 84 deletions

View File

@ -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()