Skip to content

Commit 55d5eed

Browse files
author
Chris Townsend
committed
Merge pull request #3400 from canonical/handle-amend-errors
Handle failure to convert to QCOW2 v3
1 parent 8c77fa6 commit 55d5eed

File tree

4 files changed

+51
-7
lines changed

4 files changed

+51
-7
lines changed

src/platform/backends/qemu/qemu_virtual_machine.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,19 @@ auto generate_metadata(const QStringList& platform_args, const QStringList& proc
194194
metadata[mount_data_key] = mount_args_to_json(mount_args);
195195
return metadata;
196196
}
197+
198+
void convert_to_qcow2_v3_if_necessary(const mp::Path& image_path, const std::string& vm_name)
199+
{
200+
try
201+
{
202+
// convert existing VMs to v3 too (doesn't affect images that are already v3)
203+
mp::backend::amend_to_qcow2_v3(image_path);
204+
}
205+
catch (const mp::backend::QemuImgException& e)
206+
{
207+
mpl::log(mpl::Level::error, vm_name, e.what());
208+
}
209+
}
197210
} // namespace
198211

199212
mp::QemuVirtualMachine::QemuVirtualMachine(const VirtualMachineDescription& desc,
@@ -211,8 +224,8 @@ mp::QemuVirtualMachine::QemuVirtualMachine(const VirtualMachineDescription& desc
211224
monitor{&monitor},
212225
mount_args{mount_args_from_json(monitor.retrieve_metadata_for(vm_name))}
213226
{
214-
// convert existing VMs to v3 too (doesn't affect images that are already v3)
215-
mp::backend::amend_to_qcow2_v3(desc.image.image_path); // TODO drop in a couple of releases (going in on v1.13)
227+
convert_to_qcow2_v3_if_necessary(desc.image.image_path,
228+
vm_name); // TODO drop in a couple of releases (went in on v1.13)
216229

217230
QObject::connect(
218231
this, &QemuVirtualMachine::on_delete_memory_snapshot, this,

src/platform/backends/shared/qemu_img_utils/qemu_img_utils.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ auto mp::backend::checked_exec_qemu_img(std::unique_ptr<mp::QemuImgProcessSpec>
4141
auto process_state = timeout ? process->execute(*timeout) : process->execute();
4242
if (!process_state.completed_successfully())
4343
{
44-
throw std::runtime_error(fmt::format("{}: qemu-img failed ({}) with output:\n{}",
45-
custom_error_prefix,
46-
process_state.failure_message(),
47-
process->read_all_standard_error()));
44+
throw QemuImgException{fmt::format("{}: qemu-img failed ({}) with output:\n{}",
45+
custom_error_prefix,
46+
process_state.failure_message(),
47+
process->read_all_standard_error())};
4848
}
4949

5050
return process;
@@ -90,7 +90,8 @@ mp::Path mp::backend::convert_to_qcow_if_necessary(const mp::Path& image_path)
9090
void mp::backend::amend_to_qcow2_v3(const mp::Path& image_path)
9191
{
9292
checked_exec_qemu_img(
93-
std::make_unique<mp::QemuImgProcessSpec>(QStringList{"amend", "-o", "compat=1.1", image_path}, image_path));
93+
std::make_unique<mp::QemuImgProcessSpec>(QStringList{"amend", "-o", "compat=1.1", image_path}, image_path),
94+
"Failed to amend image to QCOW2 v3");
9495
}
9596

9697
bool mp::backend::instance_image_has_snapshot(const mp::Path& image_path, QString snapshot_tag)

src/platform/backends/shared/qemu_img_utils/qemu_img_utils.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ class QemuImgProcessSpec;
3030

3131
namespace backend
3232
{
33+
class QemuImgException : public std::runtime_error
34+
{
35+
public:
36+
using std::runtime_error::runtime_error;
37+
};
38+
3339
Process::UPtr checked_exec_qemu_img(std::unique_ptr<QemuImgProcessSpec> spec,
3440
const std::string& custom_error_prefix = "Internal error",
3541
std::optional<int> timeout = std::nullopt);

tests/qemu/test_qemu_backend.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "tests/common.h"
2121
#include "tests/mock_environment_helpers.h"
22+
#include "tests/mock_logger.h"
2223
#include "tests/mock_process_factory.h"
2324
#include "tests/mock_status_monitor.h"
2425
#include "tests/stub_process_factory.h"
@@ -675,6 +676,29 @@ TEST_F(QemuBackend, ssh_hostname_timeout_throws_and_sets_unknown_state)
675676
EXPECT_EQ(machine.state, mp::VirtualMachine::State::unknown);
676677
}
677678

679+
TEST_F(QemuBackend, logsErrorOnFailureToConvertToQcow2V3UponConstruction)
680+
{
681+
mpt::StubVMStatusMonitor stub_monitor{};
682+
NiceMock<mpt::MockQemuPlatform> mock_qemu_platform{};
683+
684+
process_factory->register_callback([this](mpt::MockProcess* process) {
685+
if (process->program().contains("qemu-img") && process->arguments().contains("compat=1.1"))
686+
{
687+
mp::ProcessState exit_state{};
688+
exit_state.exit_code = 1;
689+
ON_CALL(*process, execute).WillByDefault(Return(exit_state));
690+
}
691+
else
692+
return handle_external_process_calls(process);
693+
});
694+
695+
auto logger_scope = mpt::MockLogger::inject();
696+
logger_scope.mock_logger->screen_logs(mpl::Level::error);
697+
logger_scope.mock_logger->expect_log(mpl::Level::error, "Failed to amend image to QCOW2 v3");
698+
699+
mp::QemuVirtualMachine machine{default_description, &mock_qemu_platform, stub_monitor, instance_dir.path()};
700+
}
701+
678702
TEST_F(QemuBackend, lists_no_networks)
679703
{
680704
EXPECT_CALL(*mock_qemu_platform_factory, make_qemu_platform(_)).WillOnce([this](auto...) {

0 commit comments

Comments
 (0)