#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 } }