mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-19 12:12:16 +00:00
tools: acrnctl: Use new IPC lib to connect acrn-dm
this patch aim at 1. Use new IPC lib to connect acrn-dm. 2. Export list_vm, start_vm and stop_vm and acrnd will use them later. 3. Rename vmm releated struct and function Signed-off-by: Kaige Fu <kaige.fu@intel.com> Reviewed-by: Geoffroy Van Cutsem <geoffroy.vancutsem@intel.com> Reviewed-by: Yan, Like <like.yan@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
143c49b0d2
commit
2da5e7c16a
@ -9,8 +9,8 @@ $(OUT_DIR)/libacrn-mngr.a: acrn_mngr.c acrn_mngr.h
|
||||
ar -cr $@ $(OUT_DIR)/acrn_mngr.o
|
||||
cp ./acrn_mngr.h $(OUT_DIR)/
|
||||
|
||||
$(OUT_DIR)/acrnctl: acrnctl.c
|
||||
$(CC) -o $(OUT_DIR)/acrnctl acrnctl.c -I../../devicemodel/include -Wall -g
|
||||
$(OUT_DIR)/acrnctl: acrnctl.c acrn_mngr.h
|
||||
$(CC) -o $(OUT_DIR)/acrnctl acrnctl.c acrn_vm_ops.c -I../../devicemodel/include -L$(TOOLS_OUT) -lacrn-mngr -lpthread -Wall -g
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
|
192
tools/acrn-manager/acrn_vm_ops.c
Normal file
192
tools/acrn-manager/acrn_vm_ops.c
Normal file
@ -0,0 +1,192 @@
|
||||
/**
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "acrnctl.h"
|
||||
#include "acrn_mngr.h"
|
||||
|
||||
/* List head of all vm */
|
||||
static LIST_HEAD(vmmngr_list_struct, vmmngr_struct) vmmngr_head;
|
||||
|
||||
static struct vmmngr_struct *vmmngr_list_add(char *name)
|
||||
{
|
||||
struct vmmngr_struct *s;
|
||||
|
||||
s = calloc(1, sizeof(struct vmmngr_struct));
|
||||
if (!s) {
|
||||
perror("alloc vmmngr_struct");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strncpy(s->name, name, MAX_NAME_LEN - 1);
|
||||
LIST_INSERT_HEAD(&vmmngr_head, s, list);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
struct vmmngr_struct *vmmngr_find(char *name)
|
||||
{
|
||||
struct vmmngr_struct *s;
|
||||
|
||||
LIST_FOREACH(s, &vmmngr_head, list)
|
||||
if (!strcmp(name, s->name))
|
||||
return s;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void get_vm_list(void)
|
||||
{
|
||||
char cmd[128] = { };
|
||||
char cmd_out[256] = { };
|
||||
char *vmname;
|
||||
char *pvmname = NULL;
|
||||
struct vmmngr_struct *s;
|
||||
size_t len = sizeof(cmd_out);
|
||||
|
||||
snprintf(cmd, sizeof(cmd),
|
||||
"find %s/add/ -name \"*.sh\" | "
|
||||
"sed \"s/\\/opt\\/acrn\\/conf\\/add\\///g\" | "
|
||||
"sed \"s/.sh//g\"", ACRNCTL_OPT_ROOT);
|
||||
shell_cmd(cmd, cmd_out, sizeof(cmd_out));
|
||||
|
||||
/* Properly null-terminate cmd_out */
|
||||
cmd_out[len - 1] = '\0';
|
||||
|
||||
vmname = strtok_r(cmd_out, "\n", &pvmname);
|
||||
while (vmname) {
|
||||
s = vmmngr_list_add(vmname);
|
||||
if (!s)
|
||||
continue;
|
||||
s->state = VM_CREATED;
|
||||
vmname = strtok_r(NULL, "\n", &pvmname);
|
||||
}
|
||||
|
||||
pvmname = NULL;
|
||||
|
||||
snprintf(cmd, sizeof(cmd),
|
||||
"find %s/ -name \"*monitor.*.socket\" | "
|
||||
"sed \"s/\\/run\\/acrn\\/mngr\\///g\" | "
|
||||
"awk -F. \'{ print $1 }\'", ACRN_DM_SOCK_ROOT);
|
||||
shell_cmd(cmd, cmd_out, sizeof(cmd_out));
|
||||
|
||||
/* Properly null-terminate cmd_out */
|
||||
cmd_out[len - 1] = '\0';
|
||||
|
||||
vmname = strtok_r(cmd_out, "\n", &pvmname);
|
||||
while (vmname) {
|
||||
s = vmmngr_find(vmname);
|
||||
if (s)
|
||||
s->state = VM_STARTED;
|
||||
else {
|
||||
s = vmmngr_list_add(vmname);
|
||||
if (s)
|
||||
s->state = VM_UNTRACKED;
|
||||
}
|
||||
vmname = strtok_r(NULL, "\n", &pvmname);
|
||||
}
|
||||
}
|
||||
|
||||
/* helper functions */
|
||||
int shell_cmd(const char *cmd, char *outbuf, int len)
|
||||
{
|
||||
FILE *ptr;
|
||||
char cmd_buf[256];
|
||||
int ret;
|
||||
|
||||
if (!outbuf)
|
||||
return system(cmd);
|
||||
|
||||
memset(cmd_buf, 0, sizeof(cmd_buf));
|
||||
memset(outbuf, 0, len);
|
||||
snprintf(cmd_buf, sizeof(cmd_buf), "%s 2>&1", cmd);
|
||||
ptr = popen(cmd_buf, "re");
|
||||
if (!ptr)
|
||||
return -1;
|
||||
|
||||
ret = fread(outbuf, 1, len, ptr);
|
||||
pclose(ptr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int send_msg(char *vmname, struct mngr_msg *req,
|
||||
struct mngr_msg *ack, size_t ack_len)
|
||||
{
|
||||
int fd, ret;
|
||||
|
||||
if (!vmname) {
|
||||
printf("No vmname provided\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fd = mngr_open_un(vmname, MNGR_CLIENT);
|
||||
if (fd < 0) {
|
||||
printf("%s: Unable to open %s. line %d\n", __FUNCTION__,
|
||||
vmname, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = mngr_send_msg(fd, req, ack, ack_len, 1);
|
||||
if (ret < 0) {
|
||||
printf("%s: Unable to send msg\n", __FUNCTION__);
|
||||
mngr_close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mngr_close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int list_vm()
|
||||
{
|
||||
struct vmmngr_struct *s;
|
||||
int find = 0;
|
||||
|
||||
LIST_FOREACH(s, &vmmngr_head, list) {
|
||||
printf("%s\t\t%s\n", s->name, state_str[s->state]);
|
||||
find++;
|
||||
}
|
||||
|
||||
if (!find)
|
||||
printf("There are no VMs\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int start_vm(char *vmname)
|
||||
{
|
||||
char cmd[128];
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "bash %s/add/%s.sh $(cat %s/add/%s.args)",
|
||||
ACRNCTL_OPT_ROOT, vmname, ACRNCTL_OPT_ROOT, vmname);
|
||||
|
||||
return system(cmd);
|
||||
}
|
||||
|
||||
int stop_vm(char *vmname)
|
||||
{
|
||||
struct req_dm_stop req;
|
||||
struct ack_dm_stop ack;
|
||||
|
||||
req.msg.magic = MNGR_MSG_MAGIC;
|
||||
req.msg.msgid = DM_STOP;
|
||||
req.msg.timestamp = time(NULL);
|
||||
req.msg.len = sizeof(req);
|
||||
|
||||
send_msg(vmname, (struct mngr_msg *)&req,
|
||||
(struct mngr_msg *)&ack, sizeof(ack));
|
||||
if (ack.err) {
|
||||
printf("Error happens when try to stop vm. errno(%d)\n",
|
||||
ack.err);
|
||||
}
|
||||
|
||||
return ack.err;
|
||||
}
|
@ -19,9 +19,9 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include "acrn_mngr.h"
|
||||
#include "acrnctl.h"
|
||||
|
||||
#define ACRNCTL_OPT_ROOT "/opt/acrn/conf"
|
||||
#define MAX_NAME_LEN (128)
|
||||
|
||||
#define ACMD(CMD,FUNC,DESC, VALID_ARGS) \
|
||||
{.cmd = CMD, .func = FUNC, .desc = DESC, .valid_args = VALID_ARGS}
|
||||
@ -41,166 +41,12 @@ struct acrnctl_cmd {
|
||||
int (*valid_args) (struct acrnctl_cmd * cmd, int argc, char *argv[]);
|
||||
};
|
||||
|
||||
/* helper functions */
|
||||
static int shell_cmd(const char *cmd, char *outbuf, int len)
|
||||
{
|
||||
FILE *ptr;
|
||||
char cmd_buf[256];
|
||||
int ret;
|
||||
|
||||
if (!outbuf)
|
||||
return system(cmd);
|
||||
|
||||
memset(cmd_buf, 0, sizeof(cmd_buf));
|
||||
memset(outbuf, 0, len);
|
||||
snprintf(cmd_buf, sizeof(cmd_buf), "%s 2>&1", cmd);
|
||||
ptr = popen(cmd_buf, "re");
|
||||
if (!ptr)
|
||||
return -1;
|
||||
|
||||
ret = fread(outbuf, 1, len, ptr);
|
||||
pclose(ptr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void process_msg(struct mngr_msg *msg)
|
||||
{
|
||||
if (msg->len < sizeof(*msg))
|
||||
return;
|
||||
|
||||
switch (msg->msgid) {
|
||||
case MSG_STR:
|
||||
printf("%s\n", msg->payload);
|
||||
break;
|
||||
default:
|
||||
printf("Unknown msgid(%d) received\n", msg->msgid);
|
||||
}
|
||||
}
|
||||
|
||||
/* vm states data and helper functions */
|
||||
|
||||
#define ACRN_DM_SOCK_ROOT "/run/acrn/mngr"
|
||||
|
||||
struct vmm_struct {
|
||||
char name[MAX_NAME_LEN];
|
||||
unsigned long state;
|
||||
LIST_ENTRY(vmm_struct) list;
|
||||
};
|
||||
|
||||
enum vm_state {
|
||||
VM_STATE_UNKNOWN = 0,
|
||||
VM_CREATED, /* VM created / awaiting start (boot) */
|
||||
VM_STARTED, /* VM started (booted) */
|
||||
VM_PAUSED, /* VM paused */
|
||||
VM_UNTRACKED, /* VM not created by acrnctl, or its launch script can change vm name */
|
||||
};
|
||||
|
||||
static const char *state_str[] = {
|
||||
[VM_STATE_UNKNOWN] = "unknown",
|
||||
[VM_CREATED] = "stopped",
|
||||
[VM_STARTED] = "started",
|
||||
[VM_PAUSED] = "paused",
|
||||
[VM_UNTRACKED] = "untracked",
|
||||
};
|
||||
|
||||
static LIST_HEAD(vmm_list_struct, vmm_struct) vmm_head;
|
||||
|
||||
static struct vmm_struct *vmm_list_add(char *name)
|
||||
{
|
||||
struct vmm_struct *s;
|
||||
|
||||
s = calloc(1, sizeof(struct vmm_struct));
|
||||
if (!s) {
|
||||
perror("alloc vmm_struct");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strncpy(s->name, name, MAX_NAME_LEN - 1);
|
||||
LIST_INSERT_HEAD(&vmm_head, s, list);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static struct vmm_struct *vmm_find(char *name)
|
||||
{
|
||||
struct vmm_struct *s;
|
||||
|
||||
LIST_FOREACH(s, &vmm_head, list)
|
||||
if (!strcmp(name, s->name))
|
||||
return s;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void vmm_update(void)
|
||||
{
|
||||
char cmd[128] = { };
|
||||
char cmd_out[256] = { };
|
||||
char *vmname;
|
||||
char *pvmname = NULL;
|
||||
struct vmm_struct *s;
|
||||
size_t len = sizeof(cmd_out);
|
||||
|
||||
snprintf(cmd, sizeof(cmd),
|
||||
"find %s/add/ -name \"*.sh\" | "
|
||||
"sed \"s/\\/opt\\/acrn\\/conf\\/add\\///g\" | "
|
||||
"sed \"s/.sh//g\"", ACRNCTL_OPT_ROOT);
|
||||
shell_cmd(cmd, cmd_out, sizeof(cmd_out));
|
||||
|
||||
/* Properly null-terminate cmd_out */
|
||||
cmd_out[len - 1] = '\0';
|
||||
|
||||
vmname = strtok_r(cmd_out, "\n", &pvmname);
|
||||
while (vmname) {
|
||||
s = vmm_list_add(vmname);
|
||||
if (!s)
|
||||
continue;
|
||||
s->state = VM_CREATED;
|
||||
vmname = strtok_r(NULL, "\n", &pvmname);
|
||||
}
|
||||
|
||||
pvmname = NULL;
|
||||
|
||||
snprintf(cmd, sizeof(cmd),
|
||||
"find %s/ -name \"*monitor.*.socket\" | "
|
||||
"sed \"s/\\/run\\/acrn\\/mngr\\///g\" | "
|
||||
"awk -F. \'{ print $1 }\'", ACRN_DM_SOCK_ROOT);
|
||||
shell_cmd(cmd, cmd_out, sizeof(cmd_out));
|
||||
|
||||
/* Properly null-terminate cmd_out */
|
||||
cmd_out[len - 1] = '\0';
|
||||
|
||||
vmname = strtok_r(cmd_out, "\n", &pvmname);
|
||||
while (vmname) {
|
||||
s = vmm_find(vmname);
|
||||
if (s)
|
||||
s->state = VM_STARTED;
|
||||
else {
|
||||
s = vmm_list_add(vmname);
|
||||
if (s)
|
||||
s->state = VM_UNTRACKED;
|
||||
}
|
||||
vmname = strtok_r(NULL, "\n", &pvmname);
|
||||
}
|
||||
}
|
||||
|
||||
/* There are acrnctl cmds */
|
||||
/* command: list */
|
||||
static int acrnctl_do_list(int argc, char *argv[])
|
||||
{
|
||||
struct vmm_struct *s;
|
||||
int find = 0;
|
||||
|
||||
vmm_update();
|
||||
LIST_FOREACH(s, &vmm_head, list) {
|
||||
printf("%s\t\t%s\n", s->name, state_str[s->state]);
|
||||
find++;
|
||||
}
|
||||
|
||||
if (!find)
|
||||
printf("There are no VMs\n");
|
||||
|
||||
return 0;
|
||||
get_vm_list();
|
||||
return list_vm();
|
||||
}
|
||||
|
||||
static int check_name(const char *name)
|
||||
@ -283,7 +129,7 @@ static int write_tmp_file(int fd, int n, char *word[])
|
||||
|
||||
static int acrnctl_do_add(int argc, char *argv[])
|
||||
{
|
||||
struct vmm_struct *s;
|
||||
struct vmmngr_struct *s;
|
||||
int fd, fd_tmp, ret = 0;
|
||||
char *buf;
|
||||
char *word[MAX_WORD], *line;
|
||||
@ -419,8 +265,8 @@ static int acrnctl_do_add(int argc, char *argv[])
|
||||
snprintf(cmd, sizeof(cmd), "mkdir -p %s/add", ACRNCTL_OPT_ROOT);
|
||||
system(cmd);
|
||||
|
||||
vmm_update();
|
||||
s = vmm_find(vmname);
|
||||
get_vm_list();
|
||||
s = vmmngr_find(vmname);
|
||||
if (s) {
|
||||
printf("%s(%s) already exist, can't add %s%s\n",
|
||||
vmname, state_str[s->state], argv[1], args);
|
||||
@ -462,78 +308,14 @@ static int acrnctl_do_add(int argc, char *argv[])
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* command: stop */
|
||||
static int send_stop_msg(char *vmname)
|
||||
{
|
||||
int fd, ret;
|
||||
struct sockaddr_un addr;
|
||||
struct mngr_msg msg;
|
||||
struct timeval timeout;
|
||||
fd_set rfd, wfd;
|
||||
char buf[128];
|
||||
|
||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd < 0) {
|
||||
printf("%s %d\n", __FUNCTION__, __LINE__);
|
||||
ret = -1;
|
||||
goto sock_err;
|
||||
}
|
||||
|
||||
addr.sun_family = AF_UNIX;
|
||||
snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s-monitor.socket",
|
||||
ACRN_DM_SOCK_ROOT, vmname);
|
||||
|
||||
ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
|
||||
if (ret < 0) {
|
||||
printf("%s %d\n", __FUNCTION__, __LINE__);
|
||||
goto connect_err;
|
||||
}
|
||||
|
||||
msg.magic = MNGR_MSG_MAGIC;
|
||||
msg.msgid = DM_STOP;
|
||||
msg.len = sizeof(msg);
|
||||
|
||||
timeout.tv_sec = 1; /* wait 1 second for read/write socket */
|
||||
timeout.tv_usec = 0;
|
||||
FD_ZERO(&rfd);
|
||||
FD_ZERO(&wfd);
|
||||
FD_SET(fd, &rfd);
|
||||
FD_SET(fd, &wfd);
|
||||
|
||||
select(fd + 1, NULL, &wfd, NULL, &timeout);
|
||||
|
||||
if (!FD_ISSET(fd, &wfd)) {
|
||||
printf("%s %d\n", __FUNCTION__, __LINE__);
|
||||
goto cant_write;
|
||||
}
|
||||
|
||||
ret = write(fd, &msg, sizeof(msg));
|
||||
|
||||
/* wait response */
|
||||
select(fd + 1, &rfd, NULL, NULL, &timeout);
|
||||
|
||||
if (FD_ISSET(fd, &rfd)) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
ret = read(fd, buf, sizeof(buf));
|
||||
if (ret <= sizeof(buf))
|
||||
process_msg((void *)&buf);
|
||||
}
|
||||
|
||||
cant_write:
|
||||
connect_err:
|
||||
close(fd);
|
||||
sock_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int acrnctl_do_stop(int argc, char *argv[])
|
||||
{
|
||||
struct vmm_struct *s;
|
||||
struct vmmngr_struct *s;
|
||||
int i;
|
||||
|
||||
vmm_update();
|
||||
get_vm_list();
|
||||
for (i = 1; i < argc; i++) {
|
||||
s = vmm_find(argv[i]);
|
||||
s = vmmngr_find(argv[i]);
|
||||
if (!s) {
|
||||
printf("can't find %s\n", argv[i]);
|
||||
continue;
|
||||
@ -543,7 +325,7 @@ static int acrnctl_do_stop(int argc, char *argv[])
|
||||
state_str[s->state]);
|
||||
continue;
|
||||
}
|
||||
send_stop_msg(argv[i]);
|
||||
stop_vm(argv[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -552,13 +334,13 @@ static int acrnctl_do_stop(int argc, char *argv[])
|
||||
/* command: delete */
|
||||
static int acrnctl_do_del(int argc, char *argv[])
|
||||
{
|
||||
struct vmm_struct *s;
|
||||
struct vmmngr_struct *s;
|
||||
int i;
|
||||
char cmd[128];
|
||||
|
||||
vmm_update();
|
||||
get_vm_list();
|
||||
for (i = 1; i < argc; i++) {
|
||||
s = vmm_find(argv[i]);
|
||||
s = vmmngr_find(argv[i]);
|
||||
if (!s) {
|
||||
printf("can't find %s\n", argv[i]);
|
||||
continue;
|
||||
@ -581,11 +363,10 @@ static int acrnctl_do_del(int argc, char *argv[])
|
||||
|
||||
static int acrnctl_do_start(int argc, char *argv[])
|
||||
{
|
||||
struct vmm_struct *s;
|
||||
char cmd[128];
|
||||
struct vmmngr_struct *s;
|
||||
|
||||
vmm_update();
|
||||
s = vmm_find(argv[1]);
|
||||
get_vm_list();
|
||||
s = vmmngr_find(argv[1]);
|
||||
if (!s) {
|
||||
printf("can't find %s\n", argv[1]);
|
||||
return -1;
|
||||
@ -596,10 +377,7 @@ static int acrnctl_do_start(int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "bash %s/add/%s.sh $(cat %s/add/%s.args)",
|
||||
ACRNCTL_OPT_ROOT, argv[1], ACRNCTL_OPT_ROOT, argv[1]);
|
||||
|
||||
system(cmd);
|
||||
start_vm(argv[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
58
tools/acrn-manager/acrnctl.h
Normal file
58
tools/acrn-manager/acrnctl.h
Normal file
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef _ACRNCTL_H_
|
||||
#define _ACRNCTL_H_
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
#define ACRNCTL_OPT_ROOT "/opt/acrn/conf"
|
||||
#define ACRN_DM_SOCK_ROOT "/run/acrn/mngr"
|
||||
|
||||
#define MAX_NAME_LEN (16)
|
||||
|
||||
enum vm_state {
|
||||
VM_STATE_UNKNOWN = 0,
|
||||
VM_CREATED, /* VM created / awaiting start (boot) */
|
||||
VM_STARTED, /* VM started (booted) */
|
||||
VM_PAUSED, /* VM paused */
|
||||
VM_UNTRACKED, /* VM not created by acrnctl, or its launch script can change vm name */
|
||||
};
|
||||
|
||||
static const char *state_str[] = {
|
||||
[VM_STATE_UNKNOWN] = "unknown",
|
||||
[VM_CREATED] = "stopped",
|
||||
[VM_STARTED] = "started",
|
||||
[VM_PAUSED] = "paused",
|
||||
[VM_UNTRACKED] = "untracked",
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief search all vm and store it in vmmngr_head
|
||||
*/
|
||||
void get_vm_list(void);
|
||||
|
||||
/**
|
||||
* @brief search vm indentified by vm from vmmngr_head
|
||||
*
|
||||
* @return vmmngr_struct * if find, NULL not find
|
||||
*/
|
||||
struct vmmngr_struct *vmmngr_find(char *vmname);
|
||||
|
||||
/* Per-vm vm managerment struct */
|
||||
struct vmmngr_struct {
|
||||
char name[MAX_NAME_LEN];
|
||||
unsigned long state;
|
||||
LIST_ENTRY(vmmngr_struct) list;
|
||||
};
|
||||
|
||||
int shell_cmd(const char *cmd, char *outbuf, int len);
|
||||
|
||||
/* vm life cycle ops */
|
||||
int list_vm(void);
|
||||
int stop_vm(char *vmname);
|
||||
int start_vm(char *vmname);
|
||||
|
||||
#endif /* _ACRNCTL_H_ */
|
Loading…
Reference in New Issue
Block a user