#include <nm_core.h>
#include <nm_utils.h>
#include <nm_string.h>
#include <nm_window.h>
#include <nm_network.h>
#include <nm_database.h>
#include <nm_cfg_file.h>
#include <nm_vm_control.h>
#include <nm_usb_devices.h>
#include <time.h>
enum {
NM_VIEWER_SPICE,
NM_VIEWER_VNC
};
#if defined(NM_WITH_VNC_CLIENT) || defined(NM_WITH_SPICE)
static void nm_vmctl_gen_viewer(const nm_str_t *name, uint32_t port, nm_str_t *cmd, int type);
#endif
static int nm_vmctl_clear_tap_vect(const nm_vect_t *vms);
void nm_vmctl_get_data(const nm_str_t *name, nm_vmctl_data_t *vm)
{
nm_str_t query = NM_INIT_STR;
nm_str_format(&query, NM_VM_GET_LIST_SQL, name->data);
nm_db_select(query.data, &vm->main);
nm_str_format(&query, NM_VM_GET_IFACES_SQL, name->data);
nm_db_select(query.data, &vm->ifs);
nm_str_format(&query, NM_VM_GET_DRIVES_SQL, name->data);
nm_db_select(query.data, &vm->drives);
nm_str_format(&query, NM_USB_GET_SQL, name->data);
nm_db_select(query.data, &vm->usb);
nm_str_free(&query);
}
void nm_vmctl_start(const nm_str_t *name, int flags)
{
nm_str_t buf = NM_INIT_STR;
nm_vect_t argv = NM_INIT_VECT;
nm_vmctl_data_t vm = NM_VMCTL_INIT_DATA;
nm_vect_t tfds = NM_INIT_VECT;
nm_vmctl_get_data(name, &vm);
/* check if VM is already installed */
if (nm_str_cmp_st(nm_vect_str(&vm.main, NM_SQL_INST), NM_ENABLE) == NM_OK)
{
int ch = nm_notify(_(NM_MSG_INST_CONF));
if (ch == 'y')
{
flags &= ~NM_VMCTL_TEMP;
nm_str_t query = NM_INIT_STR;
nm_str_trunc(nm_vect_str(&vm.main, NM_SQL_INST), 0);
nm_str_add_text(nm_vect_str(&vm.main, NM_SQL_INST), NM_DISABLE);
nm_str_alloc_text(&query, "UPDATE vms SET install='0' WHERE name='");
nm_str_add_str(&query, name);
nm_str_add_char(&query, '\'');
nm_db_edit(query.data);
nm_str_free(&query);
}
}
nm_vmctl_gen_cmd(&argv, &vm, name, flags, &tfds);
if (argv.n_memb > 0)
{
if (nm_spawn_process(&argv, NULL) != NM_OK)
{
nm_str_t qmp_path = NM_INIT_STR;
struct stat qmp_info;
nm_str_format(&qmp_path, "%s/%s/%s",
nm_cfg_get()->vm_dir.data, name->data, NM_VM_QMP_FILE);
/* must delete qmp sock file if exists */
if (stat(qmp_path.data, &qmp_info) != -1)
unlink(qmp_path.data);
nm_str_free(&qmp_path);
nm_warn(_(NM_MSG_START_ERR));
}
else
{
nm_cmd_str(&buf, &argv);
nm_debug("cmd=%s\n", buf.data);
nm_vmctl_log_last(&buf);
/* close all tap file descriptors */
for (size_t n = 0; n < tfds.n_memb; n++)
close(*((int *) tfds.data[n]));
}
}
nm_str_free(&buf);
nm_vect_free(&argv, NULL);
nm_vect_free(&tfds, NULL);
nm_vmctl_free_data(&vm);
}
void nm_vmctl_delete(const nm_str_t *name)
{
nm_str_t vmdir = NM_INIT_STR;
nm_str_t query = NM_INIT_STR;
nm_vect_t drives = NM_INIT_VECT;
nm_vect_t snaps = NM_INIT_VECT;
int delete_ok = NM_TRUE;
nm_str_format(&vmdir, "%s/%s/", nm_cfg_get()->vm_dir.data, name->data);
nm_str_format(&query, NM_SELECT_DRIVE_NAMES_SQL, name->data);
nm_db_select(query.data, &drives);
for (size_t n = 0; n