diff --git a/src/platform/backends/libvirt/libvirt_virtual_machine.cpp b/src/platform/backends/libvirt/libvirt_virtual_machine.cpp index d1eafaf0f4..c07cc24635 100644 --- a/src/platform/backends/libvirt/libvirt_virtual_machine.cpp +++ b/src/platform/backends/libvirt/libvirt_virtual_machine.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2020 Canonical, Ltd. + * Copyright (C) 2018-2021 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -312,13 +312,27 @@ void mp::LibVirtVirtualMachine::start() monitor->on_resume(); } -void mp::LibVirtVirtualMachine::stop() +void mp::LibVirtVirtualMachine::stop(bool force) { - shutdown(); + shutdown(force); } -void mp::LibVirtVirtualMachine::shutdown() +void mp::LibVirtVirtualMachine::shutdown(bool force) { + if (force) + { + auto domain = domain_by_name_for(vm_name, open_libvirt_connection(libvirt_wrapper).get(), libvirt_wrapper); + state = refresh_instance_state_for_domain(domain.get(), state, libvirt_wrapper); + + if (state != State::stopped && state != State::off) + { + libvirt_wrapper->virDomainDestroy(domain.get()); + update_state(); + } + + return; + } + std::unique_lock lock{state_mutex}; auto domain = domain_by_name_for(vm_name, open_libvirt_connection(libvirt_wrapper).get(), libvirt_wrapper); state = refresh_instance_state_for_domain(domain.get(), state, libvirt_wrapper); diff --git a/src/platform/backends/libvirt/libvirt_virtual_machine.h b/src/platform/backends/libvirt/libvirt_virtual_machine.h index aa932cfe5c..3e79f34f6a 100644 --- a/src/platform/backends/libvirt/libvirt_virtual_machine.h +++ b/src/platform/backends/libvirt/libvirt_virtual_machine.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2020 Canonical, Ltd. + * Copyright (C) 2018-2021 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,8 +39,8 @@ class LibVirtVirtualMachine final : public VirtualMachine ~LibVirtVirtualMachine(); void start() override; - void stop() override; - void shutdown() override; + void stop(bool force = false) override; + void shutdown(bool force = false) override; void suspend() override; State current_state() override; int ssh_port() override; diff --git a/src/platform/backends/lxd/lxd_virtual_machine.cpp b/src/platform/backends/lxd/lxd_virtual_machine.cpp index 2d7a8a27e1..acb8b44f2b 100644 --- a/src/platform/backends/lxd/lxd_virtual_machine.cpp +++ b/src/platform/backends/lxd/lxd_virtual_machine.cpp @@ -222,8 +222,35 @@ void mp::LXDVirtualMachine::start() update_state(); } -void mp::LXDVirtualMachine::stop() +void mp::LXDVirtualMachine::stop(bool force) { + if (force) + { + auto present_state = current_state(); + + if (present_state != State::stopped && present_state != State::off) + { + const QJsonObject state_json{{"action", "stop"}, {"force", true}}; + + auto state_task = lxd_request(manager, "PUT", state_url(), state_json, 5000); + + try + { + lxd_wait(manager, base_url, state_task, 60000); + } + catch (const LXDNotFoundException&) + { + } + + state = State::stopped; + } + + if (update_shutdown_status) + update_state(); + + return; + } + std::unique_lock lock{state_mutex}; auto present_state = current_state(); @@ -254,9 +281,9 @@ void mp::LXDVirtualMachine::stop() update_state(); } -void mp::LXDVirtualMachine::shutdown() +void mp::LXDVirtualMachine::shutdown(bool force) { - stop(); + stop(force); } void mp::LXDVirtualMachine::suspend() diff --git a/src/platform/backends/lxd/lxd_virtual_machine.h b/src/platform/backends/lxd/lxd_virtual_machine.h index 25f37b0509..5f52418216 100644 --- a/src/platform/backends/lxd/lxd_virtual_machine.h +++ b/src/platform/backends/lxd/lxd_virtual_machine.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2020 Canonical, Ltd. + * Copyright (C) 2019-2021 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,9 +36,9 @@ class LXDVirtualMachine final : public VirtualMachine LXDVirtualMachine(const VirtualMachineDescription& desc, VMStatusMonitor& monitor, NetworkAccessManager* manager, const QUrl& base_url, const QString& bridge_name); ~LXDVirtualMachine() override; - void stop() override; + void stop(bool force = false) override; void start() override; - void shutdown() override; + void shutdown(bool force = false) override; void suspend() override; State current_state() override; int ssh_port() override; diff --git a/src/platform/backends/qemu/qemu_virtual_machine.cpp b/src/platform/backends/qemu/qemu_virtual_machine.cpp index 2407fdba88..4debc8f5f8 100644 --- a/src/platform/backends/qemu/qemu_virtual_machine.cpp +++ b/src/platform/backends/qemu/qemu_virtual_machine.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2020 Canonical, Ltd. + * Copyright (C) 2017-2021 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -279,13 +279,25 @@ void mp::QemuVirtualMachine::start() vm_process->write(qmp_execute_json("qmp_capabilities")); } -void mp::QemuVirtualMachine::stop() +void mp::QemuVirtualMachine::stop(bool force) { - shutdown(); + shutdown(force); } -void mp::QemuVirtualMachine::shutdown() +void mp::QemuVirtualMachine::shutdown(bool force) { + if (force) + { + if (state != State::off && state != State::stopped && vm_process) + vm_process->kill(); + else + mpl::log(mpl::Level::info, vm_name, fmt::format("Ignoring forced stop")); + + return; + } + + update_shutdown_status = false; + if (state == State::suspended) { mpl::log(mpl::Level::info, vm_name, fmt::format("Ignoring shutdown issued while suspended")); diff --git a/src/platform/backends/qemu/qemu_virtual_machine.h b/src/platform/backends/qemu/qemu_virtual_machine.h index e9f835119c..205b2eed81 100644 --- a/src/platform/backends/qemu/qemu_virtual_machine.h +++ b/src/platform/backends/qemu/qemu_virtual_machine.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017-2020 Canonical, Ltd. + * Copyright (C) 2017-2021 Canonical, Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,8 +39,8 @@ class QemuVirtualMachine final : public QObject, public VirtualMachine ~QemuVirtualMachine(); void start() override; - void stop() override; - void shutdown() override; + void stop(bool force = false) override; + void shutdown(bool force = false) override; void suspend() override; State current_state() override; int ssh_port() override;