Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F3687484
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/agents/virt/server/virt-serial.c b/agents/virt/server/virt-serial.c
index 6b369bca..bfcf4de2 100644
--- a/agents/virt/server/virt-serial.c
+++ b/agents/virt/server/virt-serial.c
@@ -1,444 +1,452 @@
// #include <config.h>
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/poll.h>
#include <libvirt/libvirt.h>
#include <libxml/xmlreader.h>
#include "simpleconfig.h"
#include "debug.h"
#define DEBUG0(fmt) dbg_printf(5,"%s:%d :: " fmt "\n", \
__func__, __LINE__)
#define DEBUG1(fmt, ...) dbg_printf(5, "%s:%d: " fmt "\n", \
__func__, __LINE__, __VA_ARGS__)
+#if LIBXML_VERSION >= 21400
+#if __GNUC__ * 100 + __GNUC_MINOR__ >= 207
+#define ATTRIBUTE_UNUSED __attribute__((unused))
+#else
+#define ATTRIBUTE_UNUSED
+#endif
+#endif
+
#include "serial.h"
#define STREQ(a,b) (strcmp((a),(b)) == 0)
static pthread_t event_tid = 0;
static int run = 0;
/* Prototypes */
const char *eventToString(int event);
int myDomainEventCallback1(virConnectPtr conn, virDomainPtr dom,
int event, int detail, void *opaque);
void usage(const char *pname);
struct domain_info {
virDomainPtr dom;
virDomainEventType event;
};
static int
is_in_directory(const char *dir, const char *pathspec)
{
char *last_slash = NULL;
size_t dirlen, pathlen;
if (!dir || !pathspec)
return 0;
dirlen = strlen(dir);
pathlen = strlen(pathspec);
/*
printf("dirlen = %d pathlen = %d\n",
dirlen, pathlen);
*/
/* chop off trailing slashes */
while (dirlen && dir[dirlen-1]=='/')
--dirlen;
/* chop off leading slashes */
while (dirlen && dir[0] == '/') {
++dir;
--dirlen;
}
/* chop off leading slashes */
while (pathlen && pathspec[0] == '/') {
++pathspec;
--pathlen;
}
if (!dirlen || !pathlen)
return 0;
if (pathlen <= dirlen)
return 0;
last_slash = strrchr(pathspec, '/');
if (!last_slash)
return 0;
while (*last_slash == '/' && last_slash > pathspec)
--last_slash;
if (last_slash == pathspec)
return 0;
pathlen = last_slash - pathspec + 1;
/*printf("real dirlen = %d real pathlen = %d\n",
dirlen, pathlen);*/
if (pathlen != dirlen)
return 0;
/* todo - intelligently skip multiple slashes mid-path */
return !strncmp(dir, pathspec, dirlen);
}
static int
domainStarted(virDomainPtr mojaDomain, const char *path, int mode)
{
char dom_uuid[42];
char *xml;
xmlDocPtr doc;
xmlNodePtr cur, devices, child, serial;
xmlAttrPtr attr, attr_mode, attr_path;
if (!mojaDomain)
return -1;
virDomainGetUUIDString(mojaDomain, dom_uuid);
xml = virDomainGetXMLDesc(mojaDomain, 0);
// printf("%s\n", xml);
// @todo: free mojaDomain
// parseXML output
doc = xmlParseMemory(xml, strlen(xml));
xmlFree(xml);
cur = xmlDocGetRootElement(doc);
if (cur == NULL) {
fprintf(stderr, "Empty doc\n");
xmlFreeDoc(doc);
return -1;
}
if (xmlStrcmp(cur->name, (const xmlChar *) "domain")) {
fprintf(stderr, "no domain?\n");
xmlFreeDoc(doc);
return -1;
}
devices = cur->xmlChildrenNode;
for (devices = cur->xmlChildrenNode; devices != NULL;
devices = devices->next) {
if (xmlStrcmp(devices->name, (const xmlChar *) "devices")) {
continue;
}
for (child = devices->xmlChildrenNode; child != NULL;
child = child->next) {
if ((!mode && xmlStrcmp(child->name, (const xmlChar *) "serial")) ||
(mode && xmlStrcmp(child->name, (const xmlChar *) "channel"))) {
continue;
}
attr = xmlHasProp(child, (const xmlChar *)"type");
if (attr == NULL)
continue;
if (xmlStrcmp(attr->children->content,
(const xmlChar *) "unix")) {
continue;
}
for (serial = child->xmlChildrenNode; serial != NULL;
serial = serial->next) {
if (xmlStrcmp(serial->name,
(const xmlChar *) "source")) {
continue;
}
attr_mode = xmlHasProp(serial, (const xmlChar *)"mode");
attr_path = xmlHasProp(serial, (const xmlChar *)"path");
if (!attr_path || !attr_mode)
continue;
if (xmlStrcmp(attr_mode->children->content,
(const xmlChar *) "bind"))
continue;
if (path && !is_in_directory(path, (const char *)
attr_path->children->content))
continue;
domain_sock_setup(dom_uuid, (const char *)
attr_path->children->content);
}
}
}
xmlFreeDoc(doc);
return 0;
}
static int
registerExisting(virConnectPtr vp, const char *path, int mode)
{
int *d_ids = NULL;
int d_count, x;
virDomainPtr dom;
virDomainInfo d_info;
errno = EINVAL;
if (!vp)
return -1;
d_count = virConnectNumOfDomains(vp);
if (d_count <= 0) {
if (d_count == 0) {
/* Successful, but no domains running */
errno = 0;
return 0;
}
goto out_fail;
}
d_ids = malloc(sizeof (int) * d_count);
if (!d_ids)
goto out_fail;
if (virConnectListDomains(vp, d_ids, d_count) < 0)
goto out_fail;
/* Ok, we have the domain IDs - let's get their names and states */
for (x = 0; x < d_count; x++) {
dom = virDomainLookupByID(vp, d_ids[x]);
if (!dom) {
/* XXX doom */
goto out_fail;
}
if (virDomainGetInfo(dom, &d_info) < 0) {
/* XXX no info for the domain?!! */
virDomainFree(dom);
goto out_fail;
}
if (d_info.state != VIR_DOMAIN_SHUTOFF &&
d_info.state != VIR_DOMAIN_CRASHED)
domainStarted(dom, path, mode);
virDomainFree(dom);
}
out_fail:
free(d_ids);
return 0;
}
static int
domainStopped(virDomainPtr mojaDomain)
{
char dom_uuid[42];
if (!mojaDomain)
return -1;
virDomainGetUUIDString(mojaDomain, dom_uuid);
domain_sock_close(dom_uuid);
return 0;
}
struct event_args {
char *uri;
char *path;
int mode;
int wake_fd;
};
static void
connectClose(virConnectPtr conn ATTRIBUTE_UNUSED,
int reason,
void *opaque ATTRIBUTE_UNUSED)
{
switch (reason) {
case VIR_CONNECT_CLOSE_REASON_ERROR:
dbg_printf(2, "Connection closed due to I/O error\n");
break;
case VIR_CONNECT_CLOSE_REASON_EOF:
dbg_printf(2, "Connection closed due to end of file\n");
break;
case VIR_CONNECT_CLOSE_REASON_KEEPALIVE:
dbg_printf(2, "Connection closed due to keepalive timeout\n");
break;
case VIR_CONNECT_CLOSE_REASON_CLIENT:
dbg_printf(2, "Connection closed due to client request\n");
break;
default:
dbg_printf(2, "Connection closed due to unknown reason\n");
break;
};
run = 0;
}
int
myDomainEventCallback1(virConnectPtr conn,
virDomainPtr dom, int event, int detail, void *opaque)
{
struct event_args *args = (struct event_args *)opaque;
if (event == VIR_DOMAIN_EVENT_STARTED ||
event == VIR_DOMAIN_EVENT_STOPPED) {
virDomainRef(dom);
if (event == VIR_DOMAIN_EVENT_STARTED) {
domainStarted(dom, args->path, args->mode);
virDomainFree(dom);
if (write(args->wake_fd, "x", 1) != 1) {
dbg_printf(3, "Unable to wake up thread\n");
}
} else if (event == VIR_DOMAIN_EVENT_STOPPED) {
domainStopped(dom);
virDomainFree(dom);
}
}
return 0;
}
static void *
event_thread(void *arg)
{
struct event_args *args = (struct event_args *)arg;
virConnectPtr dconn = NULL;
int callback1ret = -1;
dbg_printf(3, "Libvirt event listener starting\n");
if (args->uri)
dbg_printf(3," * URI: %s\n", args->uri);
if (args->path)
dbg_printf(3," * Socket path: %s\n", args->path);
dbg_printf(3," * Mode: %s\n", args->mode ? "VMChannel" : "Serial");
if (virEventRegisterDefaultImpl() < 0) {
dbg_printf(1, "Failed to register default event impl\n");
goto out;
}
dconn = virConnectOpen(args->uri);
if (!dconn) {
dbg_printf(1, "Error connecting to libvirt\n");
goto out;
}
virConnectRegisterCloseCallback(dconn, connectClose, NULL, NULL);
DEBUG0("Registering domain event cbs");
registerExisting(dconn, args->path, args->mode);
callback1ret =
virConnectDomainEventRegister(dconn, myDomainEventCallback1, arg, NULL);
if (callback1ret != -1) {
if (virConnectSetKeepAlive(dconn, 5, 5) < 0) {
dbg_printf(1, "Failed to start keepalive protocol\n");
run = 0;
}
while (run) {
if (virEventRunDefaultImpl() < 0) {
dbg_printf(1, "RunDefaultImpl Failed\n");
}
}
DEBUG0("Deregistering event handlers");
virConnectDomainEventDeregister(dconn, myDomainEventCallback1);
}
DEBUG0("Closing connection");
if (dconn && virConnectClose(dconn) < 0) {
dbg_printf(1, "error closing libvirt connection\n");
}
out:
free(args->uri);
free(args->path);
free(args);
return NULL;
}
int
start_event_listener(const char *uri, const char *path, int mode, int *wake_fd)
{
struct event_args *args = NULL;
int wake_pipe[2];
virInitialize();
args = malloc(sizeof(*args));
if (!args)
return -1;
memset(args, 0, sizeof(*args));
if (pipe2(wake_pipe, O_CLOEXEC) < 0) {
goto out_fail;
}
if (uri) {
args->uri = strdup(uri);
if (args->uri == NULL)
goto out_fail;
}
if (path) {
args->path = strdup(path);
if (args->path == NULL)
goto out_fail;
}
args->mode = mode;
//args->p_tid = pthread_self();
*wake_fd = wake_pipe[0];
args->wake_fd = wake_pipe[1];
run = 1;
return pthread_create(&event_tid, NULL, event_thread, args);
out_fail:
free(args->uri);
free(args->path);
free(args);
return -1;
}
int
stop_event_listener(void)
{
run = 0;
//pthread_cancel(event_tid);
pthread_join(event_tid, NULL);
event_tid = 0;
return 0;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Apr 21, 7:31 PM (4 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1665228
Default Alt Text
(9 KB)
Attached To
Mode
rF Fence Agents
Attached
Detach File
Event Timeline
Log In to Comment