Skip to content

Commit

Permalink
vm: image format type support
Browse files Browse the repository at this point in the history
User can select `raw` or `qcow2` format

Closes #172
  • Loading branch information
0x501D committed Sep 9, 2024
1 parent 5d32170 commit 48610a1
Show file tree
Hide file tree
Showing 18 changed files with 202 additions and 67 deletions.
4 changes: 4 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
unreleased
------------------------
- Feature: image format type support: qcow2 and raw

v3.3.1 - 19.02.2024
------------------------
- Feature: error text color config option
Expand Down
9 changes: 8 additions & 1 deletion sh/upgrade_db.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
fi

DB_PATH="$1"
DB_ACTUAL_VERSION=20
DB_ACTUAL_VERSION=21
DB_CURRENT_VERSION=$(sqlite3 "$DB_PATH" -line 'PRAGMA user_version;' | sed 's/.*[[:space:]]=[[:space:]]//')
USER=$(whoami)
RC=0
Expand Down Expand Up @@ -376,6 +376,13 @@ while [ "$DB_CURRENT_VERSION" != "$DB_ACTUAL_VERSION" ]; do
) || RC=1
;;

( 20 )
(
sqlite3 "$DB_PATH" -line 'ALTER TABLE drives ADD format TEXT NOT NULL DEFAULT "qcow2";' &&
sqlite3 "$DB_PATH" -line 'PRAGMA user_version=21'
) || RC=1
;;

( * )
echo "Unsupported database user_version" >&2
exit 1
Expand Down
41 changes: 29 additions & 12 deletions src/nm_add_drive.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,24 @@
#include <nm_vm_control.h>

static const char NM_LC_DRIVE_FORM_MSG[] = "Drive interface";
static const char NM_LC_DRIVE_FORM_FORMAT[] = "Disk image format";
static const char NM_LC_DRIVE_FORM_DIS[] = "Discard mode";
static const char NM_LC_DRIVE_FORM_SZ_START[] = "Size [1-";
static const char NM_LC_DRIVE_FORM_SZ_END[] = "]Gb";

static void nm_add_drive_init_windows(nm_form_t *form);
static size_t nm_add_drive_labels_setup(void);
static void nm_add_drive_to_db(const nm_str_t *name, const nm_str_t *size,
const nm_str_t *type, const nm_vect_t *drives,
const nm_str_t *discard);
static void nm_add_drive_to_db(const nm_str_t *name,
const nm_str_t *size,
const nm_str_t *type,
const nm_vect_t *drives,
const nm_str_t *discard,
const nm_str_t *format);

enum {
NM_LBL_DRVSIZE = 0, NM_FLD_DRVSIZE,
NM_LBL_DRVTYPE, NM_FLD_DRVTYPE,
NM_LBL_FORMAT, NM_FLD_FORMAT,
NM_LBL_DISCARD, NM_FLD_DISCARD,
NM_FLD_COUNT
};
Expand Down Expand Up @@ -57,13 +62,14 @@ void nm_add_drive(const nm_str_t *name)
nm_form_t *form = NULL;
nm_str_t drv_size = NM_INIT_STR;
nm_str_t drv_type = NM_INIT_STR;
nm_str_t format = NM_INIT_STR;
nm_str_t discard = NM_INIT_STR;
nm_vmctl_data_t vm = NM_VMCTL_INIT_DATA;
nm_vect_t err = NM_INIT_VECT;
size_t msg_len;

nm_vmctl_get_data(name, &vm);
if ((vm.drives.n_memb / 4) == NM_DRIVE_LIMIT) {
if ((vm.drives.n_memb / NM_DRV_IDX_COUNT) == NM_DRIVE_LIMIT) {
nm_str_t warn_msg = NM_INIT_STR;

nm_str_format(&warn_msg, _("%zu %s"), NM_DRIVE_LIMIT, NM_NSG_DRV_LIM);
Expand Down Expand Up @@ -94,6 +100,10 @@ void nm_add_drive(const nm_str_t *name)
fields[n] = nm_field_enum_new(
n / 2, form_data, nm_form_drive_drv, false, false);
break;
case NM_FLD_FORMAT:
fields[n] = nm_field_enum_new(
n / 2, form_data, nm_form_drive_fmt, false, false);
break;
case NM_FLD_DISCARD:
fields[n] = nm_field_enum_new(
n / 2, form_data, nm_form_yes_no, false, false);
Expand All @@ -107,6 +117,7 @@ void nm_add_drive(const nm_str_t *name)

nm_add_drive_labels_setup();
set_field_buffer(fields[NM_FLD_DRVTYPE], 0, NM_DEFAULT_DRVINT);
set_field_buffer(fields[NM_FLD_FORMAT], 0, NM_DEFAULT_DRVFMT);
set_field_buffer(fields[NM_FLD_DISCARD], 0, nm_form_yes_no[1]);
nm_fields_unset_status(fields);

Expand All @@ -119,6 +130,7 @@ void nm_add_drive(const nm_str_t *name)

nm_get_field_buf(fields[NM_FLD_DRVSIZE], &drv_size);
nm_get_field_buf(fields[NM_FLD_DRVTYPE], &drv_type);
nm_get_field_buf(fields[NM_FLD_FORMAT], &format);
nm_get_field_buf(fields[NM_FLD_DISCARD], &discard);

if (!drv_size.len) {
Expand All @@ -131,10 +143,11 @@ void nm_add_drive(const nm_str_t *name)
goto out;
}

if (nm_add_drive_to_fs(name, &drv_size, &vm.drives) != NM_OK) {
if (nm_add_drive_to_fs(name, &drv_size, &vm.drives, &format) != NM_OK) {
nm_bug(_("%s: cannot create image file"), __func__);
}
nm_add_drive_to_db(name, &drv_size, &drv_type, &vm.drives, &discard);
nm_add_drive_to_db(name, &drv_size, &drv_type,
&vm.drives, &discard, &format);

out:
NM_FORM_EXIT();
Expand Down Expand Up @@ -163,6 +176,9 @@ static size_t nm_add_drive_labels_setup(void)
case NM_LBL_DRVTYPE:
nm_str_format(&buf, "%s", _(NM_LC_DRIVE_FORM_MSG));
break;
case NM_LBL_FORMAT:
nm_str_format(&buf, "%s", _(NM_LC_DRIVE_FORM_FORMAT));
break;
case NM_LBL_DISCARD:
nm_str_format(&buf, "%s", _(NM_LC_DRIVE_FORM_DIS));
break;
Expand Down Expand Up @@ -294,7 +310,7 @@ void nm_del_drive(const nm_str_t *name)
}

int nm_add_drive_to_fs(const nm_str_t *name, const nm_str_t *size,
const nm_vect_t *drives)
const nm_vect_t *drives, const nm_str_t *format)
{
nm_str_t buf = NM_INIT_STR;
nm_vect_t argv = NM_INIT_VECT;
Expand All @@ -304,7 +320,7 @@ int nm_add_drive_to_fs(const nm_str_t *name, const nm_str_t *size,

nm_vect_insert_cstr(&argv, "create");
nm_vect_insert_cstr(&argv, "-f");
nm_vect_insert_cstr(&argv, "qcow2");
nm_vect_insert_cstr(&argv, format->data);

/*
* @TODO Fix conversion from size_t to char
Expand All @@ -313,7 +329,7 @@ int nm_add_drive_to_fs(const nm_str_t *name, const nm_str_t *size,
size_t drive_count = 0;

if (drives != NULL) {
drive_count = drives->n_memb / 4;
drive_count = drives->n_memb / NM_DRV_IDX_COUNT;
}

char drv_ch = 'a' + drive_count;
Expand All @@ -339,19 +355,20 @@ int nm_add_drive_to_fs(const nm_str_t *name, const nm_str_t *size,

static void nm_add_drive_to_db(const nm_str_t *name, const nm_str_t *size,
const nm_str_t *type, const nm_vect_t *drives,
const nm_str_t *discard)
const nm_str_t *discard, const nm_str_t *format)
{
/*
* @TODO Fix conversion from size_t to char
* (might be a problem if there is too many drives)
*/
size_t drive_count = drives->n_memb / 4;
size_t drive_count = drives->n_memb / NM_DRV_IDX_COUNT;
char drv_ch = 'a' + drive_count;
nm_str_t query = NM_INIT_STR;

nm_str_format(&query, NM_SQL_DRIVES_INSERT_ADD,
name->data, name->data, drv_ch, type->data, size->data,
(nm_str_cmp_st(discard, "yes") == NM_OK) ? NM_ENABLE : NM_DISABLE);
(nm_str_cmp_st(discard, "yes") == NM_OK) ? NM_ENABLE : NM_DISABLE,
format->data);
nm_db_edit(query.data);

nm_str_free(&query);
Expand Down
2 changes: 1 addition & 1 deletion src/nm_add_drive.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ void nm_add_drive(const nm_str_t *name);
void nm_del_drive(const nm_str_t *name);

int nm_add_drive_to_fs(const nm_str_t *name, const nm_str_t *size,
const nm_vect_t *drives);
const nm_vect_t *drives, const nm_str_t *format);

static const size_t NM_DRIVE_LIMIT = 30;

Expand Down
83 changes: 63 additions & 20 deletions src/nm_add_vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,20 @@
#include <nm_cfg_file.h>
#include <nm_ovf_import.h>

static const char NM_LC_VM_FORM_NAME[] = "Name";
static const char NM_LC_VM_FORM_ARCH[] = "Architecture";
static const char NM_LC_VM_FORM_CPU[] = "CPU count";
static const char NM_LC_VM_FORM_MEM_BEGIN[] = "Memory [4-";
static const char NM_LC_VM_FORM_MEM_END[] = "]Mb";
static const char NM_LC_VM_FORM_DRV_BEGIN[] = "Disk [1-";
static const char NM_LC_VM_FORM_DRV_END[] = "]Gb";
static const char NM_LC_VM_FORM_DRV_IF[] = "Disk interface";
static const char NM_LC_VM_FORM_DRV_DIS[] = "Discard mode";
static const char NM_LC_VM_FORM_IMP_PATH[] = "Path to disk image";
static const char NM_LC_VM_FORM_INS_PATH[] = "Path to ISO/IMG";
static const char NM_LC_VM_FORM_NET_IFS[] = "Network interfaces";
static const char NM_LC_VM_FORM_NET_DRV[] = "Net driver";
static const char NM_LC_VM_FORM_NAME[] = "Name";
static const char NM_LC_VM_FORM_ARCH[] = "Architecture";
static const char NM_LC_VM_FORM_CPU[] = "CPU count";
static const char NM_LC_VM_FORM_MEM_BEGIN[] = "Memory [4-";
static const char NM_LC_VM_FORM_MEM_END[] = "]Mb";
static const char NM_LC_VM_FORM_DRV_BEGIN[] = "Disk [1-";
static const char NM_LC_VM_FORM_DRV_END[] = "]Gb";
static const char NM_LC_VM_FORM_DRV_IF[] = "Disk interface";
static const char NM_LC_VM_FORM_DRV_FORMAT[] = "Disk image format";
static const char NM_LC_VM_FORM_DRV_DIS[] = "Discard mode";
static const char NM_LC_VM_FORM_IMP_PATH[] = "Path to disk image";
static const char NM_LC_VM_FORM_INS_PATH[] = "Path to ISO/IMG";
static const char NM_LC_VM_FORM_NET_IFS[] = "Network interfaces";
static const char NM_LC_VM_FORM_NET_DRV[] = "Net driver";

static void nm_add_vm_init_windows(nm_form_t *form);
static void nm_add_vm_fields_setup(void);
Expand All @@ -41,6 +42,7 @@ enum {
NM_LBL_RAMTOT, NM_FLD_RAMTOT,
NM_LBL_DISKSZ, NM_FLD_DISKSZ,
NM_LBL_DISKIN, NM_FLD_DISKIN,
NM_LBL_DISKFMT, NM_FLD_DISKFMT,
NM_LBL_DISCARD, NM_FLD_DISCARD,
NM_LBL_SOURCE, NM_FLD_SOURCE,
NM_LBL_IFSCNT, NM_FLD_IFSCNT,
Expand Down Expand Up @@ -139,6 +141,10 @@ static void nm_add_vm_main(void)
fields[n] = nm_field_enum_new(
n / 2, form_data, nm_form_drive_drv, false, false);
break;
case NM_FLD_DISKFMT:
fields[n] = nm_field_enum_new(
n / 2, form_data, nm_form_drive_fmt, false, false);
break;
case NM_FLD_DISCARD:
fields[n] = nm_field_enum_new(
n / 2, form_data, nm_form_yes_no, false, false);
Expand Down Expand Up @@ -215,6 +221,7 @@ static void nm_add_vm_fields_setup(void)
*nm_cfg_get()->qemu_targets.data);
set_field_buffer(fields[NM_FLD_CPUNUM], 0, "1");
set_field_buffer(fields[NM_FLD_DISKIN], 0, NM_DEFAULT_DRVINT);
set_field_buffer(fields[NM_FLD_DISKFMT], 0, NM_DEFAULT_DRVFMT);
set_field_buffer(fields[NM_FLD_DISCARD], 0, nm_form_yes_no[1]);
set_field_buffer(fields[NM_FLD_IFSCNT], 0, "1");
if (import) {
Expand Down Expand Up @@ -256,6 +263,9 @@ static size_t nm_add_vm_labels_setup(void)
case NM_LBL_DISKIN:
nm_str_format(&buf, "%s", _(NM_LC_VM_FORM_DRV_IF));
break;
case NM_LBL_DISKFMT:
nm_str_format(&buf, "%s", _(NM_LC_VM_FORM_DRV_FORMAT));
break;
case NM_LBL_DISCARD:
nm_str_format(&buf, "%s", _(NM_LC_VM_FORM_DRV_DIS));
break;
Expand Down Expand Up @@ -305,6 +315,7 @@ static int nm_add_vm_get_data(nm_vm_t *vm)
if (!import) {
nm_get_field_buf(fields[NM_FLD_DISKSZ], &vm->drive.size);
}
nm_get_field_buf(fields[NM_FLD_DISKFMT], &vm->drive.format);
nm_get_field_buf(fields[NM_FLD_DISCARD], &discard);
nm_get_field_buf(fields[NM_FLD_DISKIN], &vm->drive.driver);
nm_get_field_buf(fields[NM_FLD_IFSCNT], &ifs_buf);
Expand All @@ -317,6 +328,7 @@ static int nm_add_vm_get_data(nm_vm_t *vm)
if (!import) {
nm_form_check_data(_("Disk"), vm->drive.size, err);
}
nm_form_check_data(_("Disk image format"), vm->drive.format, err);
nm_form_check_data(_("Disk interface"), vm->drive.driver, err);
nm_form_check_data(_("Discard mode"), discard, err);
nm_form_check_data(_("Path to ISO/IMG"), vm->srcp, err);
Expand Down Expand Up @@ -402,7 +414,8 @@ void nm_add_vm_to_db(nm_vm_t *vm, uint64_t mac,
vm->name.data, vm->name.data, vm->drive.driver.data,
vm->drive.size.data,
NM_ENABLE, /* boot flag */
vm->drive.discard ? NM_ENABLE : NM_DISABLE
vm->drive.discard ? NM_ENABLE : NM_DISABLE,
vm->drive.format.data
);
nm_db_edit(query.data);
} else { /* imported from OVF */
Expand All @@ -412,7 +425,8 @@ void nm_add_vm_to_db(nm_vm_t *vm, uint64_t mac,
nm_drive_file(drives->data[n])->data, NM_DEFAULT_DRVINT,
nm_drive_size(drives->data[n])->data,
n == 0 ? NM_ENABLE : NM_DISABLE, /* boot flag */
vm->drive.discard ? NM_ENABLE : NM_DISABLE
vm->drive.discard ? NM_ENABLE : NM_DISABLE,
vm->drive.format.data
);
nm_db_edit(query.data);
}
Expand Down Expand Up @@ -454,10 +468,38 @@ void nm_add_vm_to_db(nm_vm_t *vm, uint64_t mac,
nm_str_free(&query);
}

static void nm_convert_drives(const nm_str_t *vm_dir, const nm_str_t *src_img,
const nm_str_t *dst_img, const nm_str_t *format)
{
nm_str_t buf = NM_INIT_STR;
nm_vect_t argv = NM_INIT_VECT;

nm_str_format(&buf, "%s/qemu-img", nm_cfg_get()->qemu_bin_path.data);
nm_vect_insert(&argv, buf.data, buf.len + 1, NULL);

nm_vect_insert_cstr(&argv, "convert");
nm_vect_insert_cstr(&argv, "-O");
nm_vect_insert_cstr(&argv, format->data);
nm_vect_insert_cstr(&argv, src_img->data);
nm_vect_insert_cstr(&argv, dst_img->data);

nm_cmd_str(&buf, &argv);
nm_debug("add_vm: exec: %s\n", buf.data);

nm_vect_end_zero(&argv);
if (nm_spawn_process(&argv, NULL) != NM_OK) {
rmdir(vm_dir->data);
nm_bug(_("%s: cannot convert image file"), __func__);
}

nm_vect_free(&argv, NULL);
nm_str_free(&buf);
}

static void nm_add_vm_to_fs(nm_vm_t *vm)
{
nm_str_t vm_dir = NM_INIT_STR;
nm_str_t buf = NM_INIT_STR;
nm_str_t dst_img = NM_INIT_STR;

nm_str_format(&vm_dir, "%s/%s", nm_cfg_get()->vm_dir.data, vm->name.data);

Expand All @@ -467,16 +509,17 @@ static void nm_add_vm_to_fs(nm_vm_t *vm)
}

if (!import) {
if (nm_add_drive_to_fs(&vm->name, &vm->drive.size, NULL) != NM_OK) {
if (nm_add_drive_to_fs(&vm->name, &vm->drive.size,
NULL, &vm->drive.format) != NM_OK) {
nm_bug(_("%s: cannot create image file"), __func__);
}
} else {
nm_str_format(&buf, "%s/%s_a.img", vm_dir.data, vm->name.data);
nm_copy_file(&vm->srcp, &buf);
nm_str_format(&dst_img, "%s/%s_a.img", vm_dir.data, vm->name.data);
nm_convert_drives(&vm_dir, &vm->srcp, &dst_img, &vm->drive.format);
}

nm_str_free(&vm_dir);
nm_str_free(&buf);
nm_str_free(&dst_img);
}

/* vim:set ts=4 sw=4: */
3 changes: 2 additions & 1 deletion src/nm_clone_vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ static void nm_clone_vm_to_db(const nm_str_t *src, const nm_str_t *dst,
nm_vect_str(&vm->drives, NM_SQL_DRV_TYPE + idx_shift)->data,
nm_vect_str(&vm->drives, NM_SQL_DRV_SIZE + idx_shift)->data,
nm_vect_str(&vm->drives, NM_SQL_DRV_BOOT + idx_shift)->data,
nm_vect_str(&vm->drives, NM_SQL_DRV_DISC + idx_shift)->data);
nm_vect_str(&vm->drives, NM_SQL_DRV_DISC + idx_shift)->data,
nm_vect_str(&vm->drives, NM_SQL_DRV_FMT + idx_shift)->data);
nm_db_edit(query.data);

drv_ch++;
Expand Down
1 change: 1 addition & 0 deletions src/nm_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ static const char NM_DISABLE[] = "0";

static const char NM_DEFAULT_NETDRV[] = "virtio-net-pci";
static const char NM_DEFAULT_DRVINT[] = "virtio";
static const char NM_DEFAULT_DRVFMT[] = "qcow2";
static const char NM_DEFAULT_USBVER[] = "XHCI";
static const char NM_VM_PID_FILE[] = "qemu.pid";
static const char NM_VM_QMP_FILE[] = "qmp.sock";
Expand Down
Loading

0 comments on commit 48610a1

Please sign in to comment.