Skip to content

Commit

Permalink
[vm factory] added create_vm_and_instance_disk_data interface and cal…
Browse files Browse the repository at this point in the history
…l it in the daemon. Thus, remove the code cluster there.
  • Loading branch information
georgeliao committed Jan 12, 2024
1 parent d815a5e commit eddafcc
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 100 deletions.
7 changes: 7 additions & 0 deletions include/multipass/virtual_machine_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ class VirtualMachineFactory : private DisabledCopyMove
virtual ~VirtualMachineFactory() = default;
virtual VirtualMachine::UPtr create_virtual_machine(const VirtualMachineDescription& desc,
VMStatusMonitor& monitor) = 0;
virtual VirtualMachine::UPtr create_vm_and_instance_disk_data(const QString& data_directory,
const VMSpecs& src_vm_spec,
const VMSpecs& dest_vm_spec,
const std::string& source_name,
const std::string& destination_name,
const VMImage& dest_vm_image,
VMStatusMonitor& monitor) = 0;

/** Removes any resources associated with a VM of the given name.
*
Expand Down
109 changes: 10 additions & 99 deletions src/daemon/daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2692,108 +2692,19 @@ void mp::Daemon::clone(const CloneRequest* request,
clone_spec_item_and_write_to_instance_db(source_name, destination_name);

Check warning on line 2692 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2692

Added line #L2692 was not covered by tests

config->vault->clone(source_name, destination_name);

// create the directory and copy the image file and cloud-init-config.iso file
const QString backend_data_direcotry =
mp::utils::backend_directory_path(config->data_directory, config->factory->get_backend_directory_name());
const auto instances_data_directory =
std::filesystem::path(backend_data_direcotry.toStdString()) / "vault" / "instances";
const std::filesystem::path source_instance_data_directory = instances_data_directory / source_name;
const std::filesystem::path dest_instance_data_directory = instances_data_directory / destination_name;

MP_FILEOPS.copy(source_instance_data_directory,
dest_instance_data_directory,
std::filesystem::copy_options::recursive);

// move into base_virtual_machine_factory.cpp eventually
const auto& dest_vm_spec = vm_instance_specs.at(destination_name);
const YAML::Node network_data =
mpu::make_cloud_init_network_config(dest_vm_spec.default_mac_address, dest_vm_spec.extra_interfaces);
mp::CloudInitIso qemu_iso;
if (!network_data.IsNull())
{
qemu_iso.add_file("network-config", mpu::emit_cloud_config(network_data));
}
const YAML::Node meta_data = mpu::make_cloud_init_meta_config(destination_name);
qemu_iso.add_file("meta-data", mpu::emit_cloud_config(meta_data));

// create the mount folder
const fs::path cloud_init_mount_point = dest_instance_data_directory / "cidata";
if (std::error_code err; !MP_FILEOPS.create_directory(cloud_init_mount_point, err))
{
throw std::runtime_error{
fmt::format("Could not create mount point for cloud-init-config.iso file of the instance: {} ",
destination_name)};
}

// sudo mount -o loop cloud-init-config.iso
// /root/.local/share/multipassd/vault/instances/adaptive-cat-clone/cidata
const fs::path cloud_init_config_iso_file_path = dest_instance_data_directory / "cloud-init-config.iso";
const std::string mount_command = fmt::format("mount -o loop {} {}",
cloud_init_config_iso_file_path.string(),
cloud_init_mount_point.string());
if (int return_code = std::system(mount_command.c_str()); return_code != 0)
{
throw std::runtime_error{fmt::format("Error executing command : {} ", mount_command)};
}

// load files and add to qemu_iso and write to the .iso file
for (const auto filename_str : {"user-data", "vendor-data"})
{
const auto stream = MP_FILEOPS.open_read(cloud_init_mount_point / fs::path(filename_str));
std::stringstream buffer;
buffer << stream->rdbuf();
const std::string file_contents = buffer.str();
qemu_iso.add_file(filename_str, file_contents);
}
qemu_iso.write_to(QString::fromStdString(cloud_init_config_iso_file_path.string()));

// sudo umount /root/.local/share/multipassd/vault/instances/adaptive-cat-clone/cidata
const std::string unmount_command = fmt::format("umount {}", cloud_init_mount_point.string());
if (int return_code = std::system(unmount_command.c_str()); return_code != 0)
{
throw std::runtime_error{fmt::format("Error executing command : {} ", unmount_command)};
}

// delete the created mount folder
if (std::error_code err; !MP_FILEOPS.remove(cloud_init_mount_point, err))
{
throw std::runtime_error{
fmt::format("Could not remove mount point for cloud-init-config.iso file of the instance: {} ",
destination_name)};
}

const mp::VMImage dest_vm_image = fetch_image_for(destination_name, *config->factory, *config->vault);

// start to construct VirtualMachineDescription
mp::VirtualMachineDescription dest_vm_desc{dest_vm_spec.num_cores,
dest_vm_spec.mem_size,
dest_vm_spec.disk_space,
destination_name,
dest_vm_spec.default_mac_address,
dest_vm_spec.extra_interfaces,
dest_vm_spec.ssh_username,
dest_vm_image,
cloud_init_config_iso_file_path.string().c_str(),
{},
{},
{},
{}};

auto cloned_instance = operative_instances[destination_name] =
config->factory->create_virtual_machine(dest_vm_desc, *this);
cloned_instance->load_snapshots_and_update_unique_identifiers(vm_instance_specs[source_name],
dest_vm_spec,
source_name);
init_mounts(destination_name);
operative_instances[source_name]->update_clone_name_counter();
operative_instances[destination_name] =
config->factory->create_vm_and_instance_disk_data(config->data_directory,
vm_instance_specs[source_name],
vm_instance_specs[destination_name],

Check warning on line 2700 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2695-L2700

Added lines #L2695 - L2700 were not covered by tests
source_name,
destination_name,

Check warning on line 2702 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2702

Added line #L2702 was not covered by tests
dest_vm_image,
*this);

Check warning on line 2704 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2704

Added line #L2704 was not covered by tests

mpl::log(mpl::Level::info,
"general",
fmt::format("source_instance_data_directory value is : {}", source_instance_data_directory.string()));
mpl::log(mpl::Level::info,
"general",
fmt::format("dest_instance_data_directory value is : {}", dest_instance_data_directory.string()));
operative_instances[source_name]->update_clone_name_counter();
init_mounts(destination_name);

Check warning on line 2707 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2706-L2707

Added lines #L2706 - L2707 were not covered by tests

CloneReply rpc_response;
rpc_response.set_reply_message(fmt::format("Cloned from {} to {}.\n", source_name, destination_name));

Check warning on line 2710 in src/daemon/daemon.cpp

View check run for this annotation

Codecov / codecov/patch

src/daemon/daemon.cpp#L2710

Added line #L2710 was not covered by tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ mp::VirtualMachine::UPtr mp::QemuVirtualMachineFactory::create_vm_and_instance_d

mp::VirtualMachine::UPtr cloned_instance = create_virtual_machine(dest_vm_desc, monitor);
cloned_instance->load_snapshots_and_update_unique_identifiers(src_vm_spec, dest_vm_spec, source_name);

Check warning on line 154 in src/platform/backends/qemu/qemu_virtual_machine_factory.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/backends/qemu/qemu_virtual_machine_factory.cpp#L153-L154

Added lines #L153 - L154 were not covered by tests

return cloned_instance;

Check warning on line 156 in src/platform/backends/qemu/qemu_virtual_machine_factory.cpp

View check run for this annotation

Codecov / codecov/patch

src/platform/backends/qemu/qemu_virtual_machine_factory.cpp#L156

Added line #L156 was not covered by tests
}

Expand Down
2 changes: 1 addition & 1 deletion src/platform/backends/qemu/qemu_virtual_machine_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class QemuVirtualMachineFactory final : public BaseVirtualMachineFactory
const std::string& source_name,
const std::string& destination_name,
const VMImage& dest_vm_image,
VMStatusMonitor& monitor);
VMStatusMonitor& monitor) override;

VMImage prepare_source_image(const VMImage& source_image) override;
void prepare_instance_image(const VMImage& instance_image, const VirtualMachineDescription& desc) override;
Expand Down
10 changes: 10 additions & 0 deletions src/platform/backends/shared/base_virtual_machine_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ class BaseVirtualMachineFactory : public VirtualMachineFactory
{
public:
explicit BaseVirtualMachineFactory(const Path& instances_dir);
VirtualMachine::UPtr create_vm_and_instance_disk_data(const QString& data_directory,

Check warning on line 38 in src/platform/backends/shared/base_virtual_machine_factory.h

View check run for this annotation

Codecov / codecov/patch

src/platform/backends/shared/base_virtual_machine_factory.h#L38

Added line #L38 was not covered by tests
const VMSpecs& src_vm_spec,
const VMSpecs& dest_vm_spec,
const std::string& source_name,
const std::string& destination_name,
const VMImage& dest_vm_image,
VMStatusMonitor& monitor) override
{
throw NotImplementedOnThisBackendException("clone");

Check warning on line 46 in src/platform/backends/shared/base_virtual_machine_factory.h

View check run for this annotation

Codecov / codecov/patch

src/platform/backends/shared/base_virtual_machine_factory.h#L46

Added line #L46 was not covered by tests
}

void remove_resources_for(const std::string& name) final;

Expand Down
10 changes: 10 additions & 0 deletions tests/mock_virtual_machine_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ struct MockVirtualMachineFactory : public VirtualMachineFactory
{
MOCK_METHOD(VirtualMachine::UPtr, create_virtual_machine, (const VirtualMachineDescription&, VMStatusMonitor&),
(override));
MOCK_METHOD(VirtualMachine::UPtr,
create_vm_and_instance_disk_data,
(const QString&,
const VMSpecs&,
const VMSpecs&,
const std::string&,
const std::string&,
const VMImage&,
VMStatusMonitor&),
(override));
MOCK_METHOD(void, remove_resources_for, (const std::string&), (override));

MOCK_METHOD(FetchType, fetch_type, (), (override));
Expand Down
11 changes: 11 additions & 0 deletions tests/stub_virtual_machine_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ struct StubVirtualMachineFactory : public multipass::BaseVirtualMachineFactory
return std::make_unique<StubVirtualMachine>();
}

multipass::VirtualMachine::UPtr create_vm_and_instance_disk_data(const QString& data_directory,
const VMSpecs& src_vm_spec,
const VMSpecs& dest_vm_spec,
const std::string& source_name,
const std::string& destination_name,
const VMImage& dest_vm_image,
VMStatusMonitor& monitor) override
{
return std::make_unique<StubVirtualMachine>();
}

void remove_resources_for_impl(const std::string& name) override
{
}
Expand Down
10 changes: 10 additions & 0 deletions tests/test_base_virtual_machine_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ struct MockBaseFactory : mp::BaseVirtualMachineFactory

MOCK_METHOD(mp::VirtualMachine::UPtr, create_virtual_machine,
(const mp::VirtualMachineDescription&, mp::VMStatusMonitor&), (override));
MOCK_METHOD(mp::VirtualMachine::UPtr,
create_vm_and_instance_disk_data,
(const QString&,
const mp::VMSpecs&,
const mp::VMSpecs&,
const std::string&,
const std::string&,
const mp::VMImage&,
mp::VMStatusMonitor&),
(override));
MOCK_METHOD(mp::VMImage, prepare_source_image, (const mp::VMImage&), (override));
MOCK_METHOD(void, prepare_instance_image, (const mp::VMImage&, const mp::VirtualMachineDescription&), (override));
MOCK_METHOD(void, hypervisor_health_check, (), (override));
Expand Down

0 comments on commit eddafcc

Please sign in to comment.