From c644379e79262a7478a7fb9ea8001f315fdb6eaf Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 28 Mar 2024 16:18:36 -0400 Subject: Initial commit --- src/vm.cc | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/vm.cc (limited to 'src/vm.cc') diff --git a/src/vm.cc b/src/vm.cc new file mode 100644 index 0000000..29fcc43 --- /dev/null +++ b/src/vm.cc @@ -0,0 +1,85 @@ +#include "vm.h" +#include +#include + +namespace vm { + virConnectPtr conn = NULL; + + struct vmImpl { + virDomainPtr dom; + virStreamPtr stream; + std::thread receiver; + }; + + void initConn() { + if (conn == NULL) { + conn = virConnectOpen("qemu:///system"); + } + if (conn == NULL) { + std::cerr << "Failed to open connection to qemu:///system\n"; + } + } + + void clearAllVMs() { + initConn(); + virDomainPtr *domains; + int numDomains = virConnectListAllDomains(conn, &domains, 0); + for (int i = 0; i < numDomains; i++) { + virDomainDestroy(domains[i]); + virDomainFree(domains[i]); + } + free(domains); + } + + VM::VM() : data(new vmImpl()) { + initConn(); + data->stream = virStreamNew(conn, 0); + } + + VM::~VM() { + virStreamAbort(data->stream); + virStreamFree(data->stream); + } + + int VM::start(std::string config) { + data->dom = virDomainCreateXML(conn, config.c_str(), VIR_DOMAIN_START_AUTODESTROY); + if (!data->dom) { + std::cerr << "Domain creation failed\n"; + return 1; + } + return 0; + } + + void VM::stop() { + if (data->dom) { + virDomainFree(data->dom); + } + } + + void receiveTask(virStreamPtr stream, std::function receiver) { + + virStreamRecvAll(stream, + [](virStreamPtr stream, const char *data, size_t nbytes, void *opaque) { + auto *receiver = static_cast*>(opaque); + return (*receiver)(data, nbytes); + }, + &receiver); + } + + void sendTask(virStreamPtr stream, std::function sender) { + virStreamSendAll(stream, + [](virStreamPtr stream, char *data, size_t nbytes, void *opaque) { + auto *sender = static_cast*>(opaque); + return (*sender)(data, nbytes); + }, + &sender); + } + + void VM::connect(std::function receiver, std::function sender) { + if (virDomainOpenConsole(data->dom, NULL, data->stream, 0)) { + std::cerr << "Failed to open console\n"; + } + data->receiver = std::thread(receiveTask, data->stream, receiver); + sendTask(data->stream, sender); // Blocking + } +} -- cgit v1.2.3