implemented mconsole notification to check if guest came up
slightly modified menu commands
This commit is contained in:
+5
-11
@@ -26,22 +26,16 @@ struct private_dumm_t {
|
|||||||
linked_list_t *guests;
|
linked_list_t *guests;
|
||||||
};
|
};
|
||||||
|
|
||||||
static guest_t* start_guest(private_dumm_t *this, char *name, char *kernel,
|
static guest_t* create_guest(private_dumm_t *this, char *name, char *master, int mem)
|
||||||
char *master, int mem)
|
|
||||||
{
|
{
|
||||||
guest_t *guest;
|
guest_t *guest;
|
||||||
|
|
||||||
guest = guest_create(name, kernel, master, mem);
|
guest = guest_create(name, master, mem);
|
||||||
if (guest)
|
if (guest)
|
||||||
{
|
{
|
||||||
if (guest->start(guest))
|
this->guests->insert_last(this->guests, guest);
|
||||||
{
|
|
||||||
this->guests->insert_last(this->guests, guest);
|
|
||||||
return guest;
|
|
||||||
}
|
|
||||||
guest->destroy(guest);
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return guest;
|
||||||
}
|
}
|
||||||
|
|
||||||
static iterator_t* create_guest_iterator(private_dumm_t *this)
|
static iterator_t* create_guest_iterator(private_dumm_t *this)
|
||||||
@@ -73,7 +67,7 @@ dumm_t *dumm_create()
|
|||||||
{
|
{
|
||||||
private_dumm_t *this = malloc_thing(private_dumm_t);
|
private_dumm_t *this = malloc_thing(private_dumm_t);
|
||||||
|
|
||||||
this->public.start_guest = (void*)start_guest;
|
this->public.create_guest = (void*)create_guest;
|
||||||
this->public.create_guest_iterator = (void*)create_guest_iterator;
|
this->public.create_guest_iterator = (void*)create_guest_iterator;
|
||||||
this->public.destroy = (void*)destroy;
|
this->public.destroy = (void*)destroy;
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -39,13 +39,11 @@ struct dumm_t {
|
|||||||
* @brief Starts a new UML guest
|
* @brief Starts a new UML guest
|
||||||
*
|
*
|
||||||
* @param name name of the guest
|
* @param name name of the guest
|
||||||
* @param kernel kernel to boot
|
|
||||||
* @param master mounted read only master filesystem
|
* @param master mounted read only master filesystem
|
||||||
* @param mem amount of memory for guest, in MB
|
* @param mem amount of memory for guest, in MB
|
||||||
* @return guest if started, NULL if failed
|
* @return guest if started, NULL if failed
|
||||||
*/
|
*/
|
||||||
guest_t* (*start_guest) (dumm_t *this, char *name, char *kernel,
|
guest_t* (*create_guest) (dumm_t *this, char *name, char *master, int mem);
|
||||||
char *master, int mem);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create an iterator over all guests.
|
* @brief Create an iterator over all guests.
|
||||||
|
|||||||
+47
-10
@@ -38,14 +38,14 @@ struct private_guest_t {
|
|||||||
guest_t public;
|
guest_t public;
|
||||||
/** name of the guest */
|
/** name of the guest */
|
||||||
char *name;
|
char *name;
|
||||||
/** kernel to boot for guest */
|
|
||||||
char *kernel;
|
|
||||||
/** read only master filesystem guest uses */
|
/** read only master filesystem guest uses */
|
||||||
char *master;
|
char *master;
|
||||||
/** amount of memory for guest, in MB */
|
/** amount of memory for guest, in MB */
|
||||||
int mem;
|
int mem;
|
||||||
/** pid of guest child process */
|
/** pid of guest child process */
|
||||||
int pid;
|
int pid;
|
||||||
|
/** state of guest */
|
||||||
|
guest_state_t state;
|
||||||
/** log file for console 0 */
|
/** log file for console 0 */
|
||||||
int bootlog;
|
int bootlog;
|
||||||
/** mconsole to control running UML */
|
/** mconsole to control running UML */
|
||||||
@@ -54,6 +54,14 @@ struct private_guest_t {
|
|||||||
linked_list_t *ifaces;
|
linked_list_t *ifaces;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ENUM(guest_state_names, GUEST_STOPPED, GUEST_STOPPING,
|
||||||
|
"STOPPED",
|
||||||
|
"STARTING",
|
||||||
|
"RUNNING",
|
||||||
|
"PAUSED",
|
||||||
|
"STOPPING",
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of guest_t.get_name.
|
* Implementation of guest_t.get_name.
|
||||||
*/
|
*/
|
||||||
@@ -104,6 +112,22 @@ static iterator_t* create_iface_iterator(private_guest_t *this)
|
|||||||
return this->ifaces->create_iterator(this->ifaces, TRUE);
|
return this->ifaces->create_iterator(this->ifaces, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of guest_t.get_state.
|
||||||
|
*/
|
||||||
|
static guest_state_t get_state(private_guest_t *this)
|
||||||
|
{
|
||||||
|
return this->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of guest_t.get_pid.
|
||||||
|
*/
|
||||||
|
static pid_t get_pid(private_guest_t *this)
|
||||||
|
{
|
||||||
|
return this->pid;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* write format string to a buffer, and advance buffer position
|
* write format string to a buffer, and advance buffer position
|
||||||
*/
|
*/
|
||||||
@@ -129,16 +153,26 @@ static char* write_arg(char **pos, size_t *left, char *format, ...)
|
|||||||
/**
|
/**
|
||||||
* Implementation of guest_t.start.
|
* Implementation of guest_t.start.
|
||||||
*/
|
*/
|
||||||
static bool start(private_guest_t *this)
|
static bool start(private_guest_t *this, char *kernel)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char cwd[512];
|
char cwd[512];
|
||||||
|
char *notify;
|
||||||
char *pos = buf;
|
char *pos = buf;
|
||||||
char *args[16];
|
char *args[16];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
size_t left = sizeof(buf);
|
size_t left = sizeof(buf);
|
||||||
|
|
||||||
args[i++] = this->kernel;
|
if (this->state != GUEST_STOPPED)
|
||||||
|
{
|
||||||
|
DBG1("unable to start guest in state %N", guest_state_names, this->state);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
this->state = GUEST_STARTING;
|
||||||
|
|
||||||
|
notify = write_arg(&pos, &left, "%s/%s/notify", RUN_DIR, this->name);
|
||||||
|
|
||||||
|
args[i++] = kernel;
|
||||||
args[i++] = write_arg(&pos, &left, "root=/dev/root");
|
args[i++] = write_arg(&pos, &left, "root=/dev/root");
|
||||||
args[i++] = write_arg(&pos, &left, "rootfstype=hostfs");
|
args[i++] = write_arg(&pos, &left, "rootfstype=hostfs");
|
||||||
args[i++] = write_arg(&pos, &left, "rootflags=%s/%s/%s",
|
args[i++] = write_arg(&pos, &left, "rootflags=%s/%s/%s",
|
||||||
@@ -146,9 +180,11 @@ static bool start(private_guest_t *this)
|
|||||||
args[i++] = write_arg(&pos, &left, "uml_dir=%s/%s", RUN_DIR, this->name);
|
args[i++] = write_arg(&pos, &left, "uml_dir=%s/%s", RUN_DIR, this->name);
|
||||||
args[i++] = write_arg(&pos, &left, "umid=%s", this->name);
|
args[i++] = write_arg(&pos, &left, "umid=%s", this->name);
|
||||||
args[i++] = write_arg(&pos, &left, "mem=%dM", this->mem);
|
args[i++] = write_arg(&pos, &left, "mem=%dM", this->mem);
|
||||||
|
args[i++] = write_arg(&pos, &left, "mconsole=notify:%s", notify);
|
||||||
/*args[i++] = write_arg(&pos, &left, "con=pts");*/
|
/*args[i++] = write_arg(&pos, &left, "con=pts");*/
|
||||||
args[i++] = write_arg(&pos, &left, "con0=null,fd:%d", this->bootlog);
|
args[i++] = write_arg(&pos, &left, "con0=null,fd:%d", this->bootlog);
|
||||||
args[i++] = write_arg(&pos, &left, "con1=fd:0,fd:1");
|
/*args[i++] = write_arg(&pos, &left, "con1=fd:0,fd:1");*/
|
||||||
|
args[i++] = write_arg(&pos, &left, "con2=null,null");
|
||||||
args[i++] = write_arg(&pos, &left, "con3=null,null");
|
args[i++] = write_arg(&pos, &left, "con3=null,null");
|
||||||
args[i++] = write_arg(&pos, &left, "con4=null,null");
|
args[i++] = write_arg(&pos, &left, "con4=null,null");
|
||||||
args[i++] = write_arg(&pos, &left, "con5=null,null");
|
args[i++] = write_arg(&pos, &left, "con5=null,null");
|
||||||
@@ -172,8 +208,7 @@ static bool start(private_guest_t *this)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* open mconsole */
|
/* open mconsole */
|
||||||
snprintf(buf, sizeof(buf), "%s/%s/%s/mconsole", RUN_DIR, this->name, this->name);
|
this->mconsole = mconsole_create(notify);
|
||||||
this->mconsole = mconsole_create(buf);
|
|
||||||
if (this->mconsole == NULL)
|
if (this->mconsole == NULL)
|
||||||
{
|
{
|
||||||
DBG1("opening mconsole at '%s' failed, stopping guest", buf);
|
DBG1("opening mconsole at '%s' failed, stopping guest", buf);
|
||||||
@@ -181,6 +216,7 @@ static bool start(private_guest_t *this)
|
|||||||
this->pid = 0;
|
this->pid = 0;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
this->state = GUEST_RUNNING;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,7 +329,6 @@ static void destroy(private_guest_t *this)
|
|||||||
this->ifaces->destroy_offset(this->ifaces, offsetof(iface_t, destroy));
|
this->ifaces->destroy_offset(this->ifaces, offsetof(iface_t, destroy));
|
||||||
DESTROY_IF(this->mconsole);
|
DESTROY_IF(this->mconsole);
|
||||||
free(this->name);
|
free(this->name);
|
||||||
free(this->kernel);
|
|
||||||
free(this->master);
|
free(this->master);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
@@ -301,11 +336,13 @@ static void destroy(private_guest_t *this)
|
|||||||
/**
|
/**
|
||||||
* create the guest instance, including required dirs and mounts
|
* create the guest instance, including required dirs and mounts
|
||||||
*/
|
*/
|
||||||
guest_t *guest_create(char *name, char *kernel, char *master, int mem)
|
guest_t *guest_create(char *name, char *master, int mem)
|
||||||
{
|
{
|
||||||
private_guest_t *this = malloc_thing(private_guest_t);
|
private_guest_t *this = malloc_thing(private_guest_t);
|
||||||
|
|
||||||
this->public.get_name = (void*)get_name;
|
this->public.get_name = (void*)get_name;
|
||||||
|
this->public.get_pid = (pid_t(*)(guest_t*))get_pid;
|
||||||
|
this->public.get_state = (guest_state_t(*)(guest_t*))get_state;
|
||||||
this->public.create_iface = (iface_t*(*)(guest_t*,char*))create_iface;
|
this->public.create_iface = (iface_t*(*)(guest_t*,char*))create_iface;
|
||||||
this->public.create_iface_iterator = (iterator_t*(*)(guest_t*))create_iface_iterator;
|
this->public.create_iface_iterator = (iterator_t*(*)(guest_t*))create_iface_iterator;
|
||||||
this->public.start = (void*)start;
|
this->public.start = (void*)start;
|
||||||
@@ -320,10 +357,10 @@ guest_t *guest_create(char *name, char *kernel, char *master, int mem)
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->name = strdup(name);
|
this->name = strdup(name);
|
||||||
this->kernel = strdup(kernel);
|
|
||||||
this->master = strdup(master);
|
this->master = strdup(master);
|
||||||
this->mem = mem;
|
this->mem = mem;
|
||||||
this->pid = 0;
|
this->pid = 0;
|
||||||
|
this->state = GUEST_STOPPED;
|
||||||
this->bootlog = open_bootlog(name);
|
this->bootlog = open_bootlog(name);
|
||||||
this->mconsole = NULL;
|
this->mconsole = NULL;
|
||||||
this->ifaces = linked_list_create();
|
this->ifaces = linked_list_create();
|
||||||
|
|||||||
+39
-3
@@ -21,6 +21,29 @@
|
|||||||
|
|
||||||
#include "iface.h"
|
#include "iface.h"
|
||||||
|
|
||||||
|
typedef enum guest_state_t guest_state_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief State of a guest (started, stopped, ...)
|
||||||
|
*/
|
||||||
|
enum guest_state_t {
|
||||||
|
/** guest kernel not running at all */
|
||||||
|
GUEST_STOPPED,
|
||||||
|
/** kernel started, but not yet available */
|
||||||
|
GUEST_STARTING,
|
||||||
|
/** guest is up and running */
|
||||||
|
GUEST_RUNNING,
|
||||||
|
/** guest has been paused */
|
||||||
|
GUEST_PAUSED,
|
||||||
|
/** guest is stopping (shutting down) */
|
||||||
|
GUEST_STOPPING,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* string mappings for guest_state_t
|
||||||
|
*/
|
||||||
|
extern enum_name_t *guest_state_names;
|
||||||
|
|
||||||
typedef struct guest_t guest_t;
|
typedef struct guest_t guest_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,12 +58,26 @@ struct guest_t {
|
|||||||
*/
|
*/
|
||||||
char* (*get_name) (guest_t *this);
|
char* (*get_name) (guest_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the process ID of the guest child process.
|
||||||
|
*
|
||||||
|
* @return name of the guest
|
||||||
|
*/
|
||||||
|
pid_t (*get_pid) (guest_t *this);
|
||||||
|
/**
|
||||||
|
* @brief Get the state of the guest (stopped, started, etc.).
|
||||||
|
*
|
||||||
|
* @return guests state
|
||||||
|
*/
|
||||||
|
guest_state_t (*get_state)(guest_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Start the guest.
|
* @brief Start the guest.
|
||||||
*
|
*
|
||||||
|
* @param kernel kernel to boot for this guest
|
||||||
* @return TRUE if guest successfully started
|
* @return TRUE if guest successfully started
|
||||||
*/
|
*/
|
||||||
bool (*start) (guest_t *this);
|
bool (*start) (guest_t *this, char *kernel);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Kill the guest.
|
* @brief Kill the guest.
|
||||||
@@ -74,11 +111,10 @@ struct guest_t {
|
|||||||
* @brief Create a new, unstarted guest.
|
* @brief Create a new, unstarted guest.
|
||||||
*
|
*
|
||||||
* @param name name of the guest
|
* @param name name of the guest
|
||||||
* @param kernel kernel to boot for this guest
|
|
||||||
* @param master read-only master filesystem for guest
|
* @param master read-only master filesystem for guest
|
||||||
* @param mem amount of memory to give the guest
|
* @param mem amount of memory to give the guest
|
||||||
*/
|
*/
|
||||||
guest_t *guest_create(char *name, char *kernel, char *master, int mem);
|
guest_t *guest_create(char *name, char *master, int mem);
|
||||||
|
|
||||||
#endif /* GUEST_H */
|
#endif /* GUEST_H */
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
* Copyright (C) 2002 Jeff Dike
|
* Copyright (C) 2002 Jeff Dike
|
||||||
*
|
*
|
||||||
* Based on the "tunctl" utlity from Jeff Dike.
|
* Based on the "tunctl" utility from Jeff Dike.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
|||||||
+123
-87
@@ -39,23 +39,21 @@ static void usage()
|
|||||||
*/
|
*/
|
||||||
static void help()
|
static void help()
|
||||||
{
|
{
|
||||||
printf("start name=<name> [options] start a guest named <name>\n");
|
printf("create name=<name> start a guest named <name>\n");
|
||||||
printf(" additional options:\n");
|
printf(" [master=<dir>] read only master root filesystem\n");
|
||||||
printf(" kernel=<uml-kernel>\n");
|
printf(" [memory=<MB>] guest main memory in megabyte\n");
|
||||||
printf(" master=<read-only root files>\n");
|
|
||||||
printf(" memory=<guest memory in MB>\n");
|
|
||||||
printf("list list running guests\n");
|
printf("list list running guests\n");
|
||||||
printf("guest <name> open guest menu for <name>\n");
|
printf("guest <name> open guest menu for <name>\n");
|
||||||
printf("help show this help\n");
|
printf("help show this help\n");
|
||||||
printf("quit kill quests and exit\n");
|
printf("quit kill quests and exit\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* help for guest shell
|
* help for guest shell
|
||||||
*/
|
*/
|
||||||
static void help_guest()
|
static void help_guest()
|
||||||
{
|
{
|
||||||
|
printf("start [kernel=<uml-kernel>] start the guest\n");
|
||||||
printf("addif <name> add an interface to the guest\n");
|
printf("addif <name> add an interface to the guest\n");
|
||||||
printf("delif <name> remove the interface\n");
|
printf("delif <name> remove the interface\n");
|
||||||
printf("listif list guests interfaces\n");
|
printf("listif list guests interfaces\n");
|
||||||
@@ -63,83 +61,6 @@ static void help_guest()
|
|||||||
printf("quit quit the guest menu\n");
|
printf("quit quit the guest menu\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* start an UML guest
|
|
||||||
*/
|
|
||||||
static void start(dumm_t *dumm, char *line)
|
|
||||||
{
|
|
||||||
enum {
|
|
||||||
NAME = 0,
|
|
||||||
MASTER,
|
|
||||||
KERNEL,
|
|
||||||
MEMORY,
|
|
||||||
};
|
|
||||||
char *const opts[] = {
|
|
||||||
[NAME] = "name",
|
|
||||||
[MASTER] = "master",
|
|
||||||
[KERNEL] = "kernel",
|
|
||||||
[MEMORY] = "memory",
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
char *value;
|
|
||||||
char *name = NULL;
|
|
||||||
char *kernel = NULL;
|
|
||||||
char *master = NULL;
|
|
||||||
int mem = 0;
|
|
||||||
|
|
||||||
while (TRUE)
|
|
||||||
{
|
|
||||||
switch (getsubopt(&line, opts, &value))
|
|
||||||
{
|
|
||||||
case NAME:
|
|
||||||
name = value;
|
|
||||||
continue;
|
|
||||||
case MASTER:
|
|
||||||
master = value;
|
|
||||||
continue;
|
|
||||||
case KERNEL:
|
|
||||||
kernel = value;
|
|
||||||
continue;
|
|
||||||
case MEMORY:
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
mem = atoi(value);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (name == NULL)
|
|
||||||
{
|
|
||||||
printf("option 'name' is required.\n");
|
|
||||||
help();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (kernel == NULL)
|
|
||||||
{
|
|
||||||
kernel = "./linux";
|
|
||||||
}
|
|
||||||
if (master == NULL)
|
|
||||||
{
|
|
||||||
master = "master";
|
|
||||||
}
|
|
||||||
if (mem == 0)
|
|
||||||
{
|
|
||||||
mem = 128;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dumm->start_guest(dumm, name, kernel, master, mem))
|
|
||||||
{
|
|
||||||
printf("starting guest '%s'\n", name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("starting guest '%s' failed\n", name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add an iface to a guest
|
* add an iface to a guest
|
||||||
*/
|
*/
|
||||||
@@ -207,6 +128,49 @@ static void list_if(guest_t *guest)
|
|||||||
iterator->destroy(iterator);
|
iterator->destroy(iterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* start an UML guest
|
||||||
|
*/
|
||||||
|
static void start_guest(guest_t *guest, char *line)
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
KERNEL = 0,
|
||||||
|
};
|
||||||
|
char *const opts[] = {
|
||||||
|
[KERNEL] = "kernel",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
char *value;
|
||||||
|
char *kernel = NULL;
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
switch (getsubopt(&line, opts, &value))
|
||||||
|
{
|
||||||
|
case KERNEL:
|
||||||
|
kernel = value;
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (kernel == NULL)
|
||||||
|
{
|
||||||
|
kernel = "./linux";
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("starting guest '%s'... \n", guest->get_name(guest));
|
||||||
|
if (guest->start(guest, kernel))
|
||||||
|
{
|
||||||
|
printf("guest '%s' is up\n", guest->get_name(guest));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("failed to start guest '%s'!\n", guest->get_name(guest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* subshell for guests
|
* subshell for guests
|
||||||
*/
|
*/
|
||||||
@@ -246,6 +210,7 @@ static void guest(dumm_t *dumm, char *name)
|
|||||||
enum {
|
enum {
|
||||||
QUIT = 0,
|
QUIT = 0,
|
||||||
HELP,
|
HELP,
|
||||||
|
START,
|
||||||
ADDIF,
|
ADDIF,
|
||||||
DELIF,
|
DELIF,
|
||||||
LISTIF,
|
LISTIF,
|
||||||
@@ -253,6 +218,7 @@ static void guest(dumm_t *dumm, char *name)
|
|||||||
char *const opts[] = {
|
char *const opts[] = {
|
||||||
[QUIT] = "quit",
|
[QUIT] = "quit",
|
||||||
[HELP] = "help",
|
[HELP] = "help",
|
||||||
|
[START] = "start",
|
||||||
[ADDIF] = "addif",
|
[ADDIF] = "addif",
|
||||||
[DELIF] = "delif",
|
[DELIF] = "delif",
|
||||||
[LISTIF] = "listif",
|
[LISTIF] = "listif",
|
||||||
@@ -285,6 +251,9 @@ static void guest(dumm_t *dumm, char *name)
|
|||||||
case HELP:
|
case HELP:
|
||||||
help_guest();
|
help_guest();
|
||||||
continue;
|
continue;
|
||||||
|
case START:
|
||||||
|
start_guest(guest, pos);
|
||||||
|
continue;
|
||||||
case ADDIF:
|
case ADDIF:
|
||||||
add_if(guest, pos);
|
add_if(guest, pos);
|
||||||
continue;
|
continue;
|
||||||
@@ -302,6 +271,73 @@ static void guest(dumm_t *dumm, char *name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create an UML guest
|
||||||
|
*/
|
||||||
|
static void create_guest(dumm_t *dumm, char *line)
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
NAME = 0,
|
||||||
|
MASTER,
|
||||||
|
MEMORY,
|
||||||
|
};
|
||||||
|
char *const opts[] = {
|
||||||
|
[NAME] = "name",
|
||||||
|
[MASTER] = "master",
|
||||||
|
[MEMORY] = "memory",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
char *value;
|
||||||
|
char *name = NULL;
|
||||||
|
char *master = NULL;
|
||||||
|
int mem = 0;
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
switch (getsubopt(&line, opts, &value))
|
||||||
|
{
|
||||||
|
case NAME:
|
||||||
|
name = value;
|
||||||
|
continue;
|
||||||
|
case MASTER:
|
||||||
|
master = value;
|
||||||
|
continue;
|
||||||
|
case MEMORY:
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
mem = atoi(value);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (name == NULL)
|
||||||
|
{
|
||||||
|
printf("option 'name' is required.\n");
|
||||||
|
help();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (master == NULL)
|
||||||
|
{
|
||||||
|
master = "master";
|
||||||
|
}
|
||||||
|
if (mem == 0)
|
||||||
|
{
|
||||||
|
mem = 128;
|
||||||
|
}
|
||||||
|
if (dumm->create_guest(dumm, name, master, mem))
|
||||||
|
{
|
||||||
|
printf("guest '%s' created\n", name);
|
||||||
|
guest(dumm, name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("failed to create guest '%s'!\n", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* list running UML guests
|
* list running UML guests
|
||||||
*/
|
*/
|
||||||
@@ -370,14 +406,14 @@ int main(int argc, char *argv[])
|
|||||||
enum {
|
enum {
|
||||||
QUIT = 0,
|
QUIT = 0,
|
||||||
HELP,
|
HELP,
|
||||||
START,
|
CREATE,
|
||||||
LIST,
|
LIST,
|
||||||
GUEST,
|
GUEST,
|
||||||
};
|
};
|
||||||
char *const opts[] = {
|
char *const opts[] = {
|
||||||
[QUIT] = "quit",
|
[QUIT] = "quit",
|
||||||
[HELP] = "help",
|
[HELP] = "help",
|
||||||
[START] = "start",
|
[CREATE] = "create",
|
||||||
[LIST] = "list",
|
[LIST] = "list",
|
||||||
[GUEST] = "guest",
|
[GUEST] = "guest",
|
||||||
NULL
|
NULL
|
||||||
@@ -410,8 +446,8 @@ int main(int argc, char *argv[])
|
|||||||
case HELP:
|
case HELP:
|
||||||
help();
|
help();
|
||||||
continue;
|
continue;
|
||||||
case START:
|
case CREATE:
|
||||||
start(dumm, pos);
|
create_guest(dumm, pos);
|
||||||
continue;
|
continue;
|
||||||
case LIST:
|
case LIST:
|
||||||
list(dumm);
|
list(dumm);
|
||||||
|
|||||||
+129
-31
@@ -3,7 +3,7 @@
|
|||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
* Copyright (C) 2001-2004 Jeff Dike
|
* Copyright (C) 2001-2004 Jeff Dike
|
||||||
*
|
*
|
||||||
* Based on the "uml_mconsole" utilty from Jeff Dike.
|
* Based on the "uml_mconsole" utility from Jeff Dike.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the
|
* under the terms of the GNU General Public License as published by the
|
||||||
@@ -36,28 +36,57 @@ struct private_mconsole_t {
|
|||||||
/** public interface */
|
/** public interface */
|
||||||
mconsole_t public;
|
mconsole_t public;
|
||||||
/** mconsole socket */
|
/** mconsole socket */
|
||||||
int socket;
|
int console;
|
||||||
|
/** notify socket */
|
||||||
|
int notify;
|
||||||
/** address of uml socket */
|
/** address of uml socket */
|
||||||
struct sockaddr_un uml;
|
struct sockaddr_un uml;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mconsole message format from "arch/um/include/mconsole.h"
|
||||||
|
*/
|
||||||
|
typedef struct mconsole_request mconsole_request;
|
||||||
|
/** mconsole request message */
|
||||||
|
struct mconsole_request {
|
||||||
|
u_int32_t magic;
|
||||||
|
u_int32_t version;
|
||||||
|
u_int32_t len;
|
||||||
|
char data[MCONSOLE_MAX_DATA];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct mconsole_reply mconsole_reply;
|
||||||
|
/** mconsole reply message */
|
||||||
|
struct mconsole_reply {
|
||||||
|
u_int32_t err;
|
||||||
|
u_int32_t more;
|
||||||
|
u_int32_t len;
|
||||||
|
char data[MCONSOLE_MAX_DATA];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct mconsole_notify mconsole_notify;
|
||||||
|
/** mconsole notify message */
|
||||||
|
struct mconsole_notify {
|
||||||
|
u_int32_t magic;
|
||||||
|
u_int32_t version;
|
||||||
|
enum {
|
||||||
|
MCONSOLE_SOCKET,
|
||||||
|
MCONSOLE_PANIC,
|
||||||
|
MCONSOLE_HANG,
|
||||||
|
MCONSOLE_USER_NOTIFY,
|
||||||
|
} type;
|
||||||
|
u_int32_t len;
|
||||||
|
char data[MCONSOLE_MAX_DATA];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* send a request to UML using mconsole
|
* send a request to UML using mconsole
|
||||||
*/
|
*/
|
||||||
static bool request(private_mconsole_t *this, char *command)
|
static bool request(private_mconsole_t *this, char *command)
|
||||||
{
|
{
|
||||||
struct {
|
mconsole_request request;
|
||||||
u_int32_t magic;
|
mconsole_reply reply;
|
||||||
u_int32_t version;
|
|
||||||
u_int32_t len;
|
|
||||||
char data[MCONSOLE_MAX_DATA];
|
|
||||||
} request;
|
|
||||||
struct {
|
|
||||||
u_int32_t err;
|
|
||||||
u_int32_t more;
|
|
||||||
u_int32_t len;
|
|
||||||
char data[MCONSOLE_MAX_DATA];
|
|
||||||
} reply;
|
|
||||||
bool first = TRUE, good = TRUE;
|
bool first = TRUE, good = TRUE;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
@@ -67,7 +96,7 @@ static bool request(private_mconsole_t *this, char *command)
|
|||||||
request.len = min(strlen(command), sizeof(reply.data) - 1);
|
request.len = min(strlen(command), sizeof(reply.data) - 1);
|
||||||
strncpy(request.data, command, request.len);
|
strncpy(request.data, command, request.len);
|
||||||
|
|
||||||
if (sendto(this->socket, &request, sizeof(request), 0,
|
if (sendto(this->console, &request, sizeof(request), 0,
|
||||||
(struct sockaddr*)&this->uml, sizeof(this->uml)) < 0)
|
(struct sockaddr*)&this->uml, sizeof(this->uml)) < 0)
|
||||||
{
|
{
|
||||||
DBG1("sending mconsole command to UML failed: %m");
|
DBG1("sending mconsole command to UML failed: %m");
|
||||||
@@ -75,7 +104,7 @@ static bool request(private_mconsole_t *this, char *command)
|
|||||||
}
|
}
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
len = recvfrom(this->socket, &reply, sizeof(reply), 0, NULL, 0);
|
len = recvfrom(this->console, &reply, sizeof(reply), 0, NULL, 0);
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
{
|
{
|
||||||
DBG1("receiving from mconsole failed: %m");
|
DBG1("receiving from mconsole failed: %m");
|
||||||
@@ -129,41 +158,110 @@ static bool del_iface(private_mconsole_t *this, char *guest)
|
|||||||
*/
|
*/
|
||||||
static void destroy(private_mconsole_t *this)
|
static void destroy(private_mconsole_t *this)
|
||||||
{
|
{
|
||||||
close(this->socket);
|
close(this->console);
|
||||||
|
close(this->notify);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setup the mconsole notify connection and wait for its readyness
|
||||||
|
*/
|
||||||
|
static bool wait_for_notify(private_mconsole_t *this, char *nsock)
|
||||||
|
{
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
mconsole_notify notify;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
this->notify = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||||
|
if (this->notify < 0)
|
||||||
|
{
|
||||||
|
DBG1("opening mconsole notify socket failed: %m");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
strncpy(addr.sun_path, nsock, sizeof(addr));
|
||||||
|
if (bind(this->notify, (struct sockaddr*)&addr, sizeof(addr)) < 0)
|
||||||
|
{
|
||||||
|
DBG1("binding mconsole notify socket to '%s' failed: %m", nsock);
|
||||||
|
close(this->notify);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
len = recvfrom(this->notify, ¬ify, sizeof(notify), 0, NULL, 0);
|
||||||
|
if (len < 0 || len >= sizeof(notify))
|
||||||
|
{
|
||||||
|
DBG1("reading from mconsole notify socket failed: %m");
|
||||||
|
close(this->notify);
|
||||||
|
unlink(nsock);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (notify.magic != MCONSOLE_MAGIC ||
|
||||||
|
notify.version != MCONSOLE_VERSION ||
|
||||||
|
notify.type != MCONSOLE_SOCKET)
|
||||||
|
{
|
||||||
|
DBG1("received unexpected message from mconsole notify socket: %b",
|
||||||
|
¬ify, sizeof(notify));
|
||||||
|
close(this->notify);
|
||||||
|
unlink(nsock);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
memset(&this->uml, 0, sizeof(this->uml));
|
||||||
|
this->uml.sun_family = AF_UNIX;
|
||||||
|
strncpy(this->uml.sun_path, (char*)¬ify.data, sizeof(this->uml.sun_path));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setup the mconsole console connection
|
||||||
|
*/
|
||||||
|
static bool setup_console(private_mconsole_t *this)
|
||||||
|
{
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
|
||||||
|
this->console = socket(AF_UNIX, SOCK_DGRAM, 0);
|
||||||
|
if (this->console < 0)
|
||||||
|
{
|
||||||
|
DBG1("opening mconsole socket failed: %m");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
snprintf(&addr.sun_path[1], sizeof(addr.sun_path), "%5d-%d",
|
||||||
|
getpid(), this->console);
|
||||||
|
if (bind(this->console, (struct sockaddr*)&addr, sizeof(addr)) < 0)
|
||||||
|
{
|
||||||
|
DBG1("binding mconsole socket to '%s' failed: %m", &addr.sun_path[1]);
|
||||||
|
close(this->console);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* create the mconsole instance
|
* create the mconsole instance
|
||||||
*/
|
*/
|
||||||
mconsole_t *mconsole_create(char *sock)
|
mconsole_t *mconsole_create(char *notify)
|
||||||
{
|
{
|
||||||
struct sockaddr_un addr;
|
|
||||||
private_mconsole_t *this = malloc_thing(private_mconsole_t);
|
private_mconsole_t *this = malloc_thing(private_mconsole_t);
|
||||||
|
|
||||||
this->public.add_iface = (bool(*)(mconsole_t*, char *guest, char *host))add_iface;
|
this->public.add_iface = (bool(*)(mconsole_t*, char *guest, char *host))add_iface;
|
||||||
this->public.del_iface = (bool(*)(mconsole_t*, char *guest))del_iface;
|
this->public.del_iface = (bool(*)(mconsole_t*, char *guest))del_iface;
|
||||||
this->public.destroy = (void*)destroy;
|
this->public.destroy = (void*)destroy;
|
||||||
|
|
||||||
this->socket = socket(AF_UNIX, SOCK_DGRAM, 0);
|
if (!wait_for_notify(this, notify))
|
||||||
if (this->socket < 0)
|
|
||||||
{
|
{
|
||||||
DBG1("opening mconsole socket failed: %m");
|
|
||||||
free(this);
|
free(this);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memset(&addr, 0, sizeof(addr));
|
|
||||||
addr.sun_family = AF_UNIX;
|
if (!setup_console(this))
|
||||||
snprintf(&addr.sun_path[1], sizeof(addr.sun_path), "%5d-%s", getpid(), sock);
|
|
||||||
if (bind(this->socket, (struct sockaddr*)&addr, sizeof(addr)) < 0)
|
|
||||||
{
|
{
|
||||||
DBG1("binding mconsole socket failed: %m");
|
close(this->notify);
|
||||||
destroy(this);
|
unlink(notify);
|
||||||
|
free(this);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memset(&this->uml, 0, sizeof(this->uml));
|
unlink(notify);
|
||||||
this->uml.sun_family = AF_UNIX;
|
|
||||||
strncpy(this->uml.sun_path, sock, sizeof(this->uml.sun_path));
|
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-2
@@ -51,10 +51,13 @@ struct mconsole_t {
|
|||||||
/**
|
/**
|
||||||
* @brief Create a new mconsole connection to a guest.
|
* @brief Create a new mconsole connection to a guest.
|
||||||
*
|
*
|
||||||
* @param socket guests mconsole socket
|
* Waits for a notification from the guest through the notify socket and tries
|
||||||
|
* to connect to the mconsole socket supplied in the received notification.
|
||||||
|
*
|
||||||
|
* @param notify unix notify socket path
|
||||||
* @return mconsole instance, or NULL if failed
|
* @return mconsole instance, or NULL if failed
|
||||||
*/
|
*/
|
||||||
mconsole_t *mconsole_create(char *socket);
|
mconsole_t *mconsole_create(char *notify);
|
||||||
|
|
||||||
#endif /* MCONSOLE_H */
|
#endif /* MCONSOLE_H */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user