From 14d8b0310c2cb7acec75e1d699b266381c77dc60 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 4 Sep 2008 09:01:55 +0200 Subject: [PATCH] Intermediate update... consider this version completely broken --- domumdns.c | 2 +- handler_avahi.c | 11 ++- handler_clusterstats.c | 5 -- handler_virt.c | 237 +++++++++++++++++++++++++++++++++++++++++++++++-- handler_virt.h | 6 ++ 5 files changed, 240 insertions(+), 21 deletions(-) diff --git a/domumdns.c b/domumdns.c index 58a0e11..0f4a894 100644 --- a/domumdns.c +++ b/domumdns.c @@ -188,7 +188,7 @@ static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UN case AVAHI_CLIENT_FAILURE: fprintf(stderr, "Client failure: %s\n", avahi_strerror(avahi_client_errno(c))); - avahi_simple_poll_quit(simple_poll); + // avahi_simple_poll_quit(simple_poll); break; diff --git a/handler_avahi.c b/handler_avahi.c index 0d70930..e50e4cc 100644 --- a/handler_avahi.c +++ b/handler_avahi.c @@ -48,8 +48,8 @@ PLUGIN_INFO_HANDLER_EASIEST_INIT (avahi, http_get); /* Methods implementation */ -static ret_t -props_free (cherokee_handler_avahi_props_t *props) +ret_t +cherokee_handler_avahi_props_free (cherokee_handler_avahi_props_t *props) { if (props->threaded_poll) avahi_threaded_poll_stop(props->threaded_poll); @@ -66,7 +66,6 @@ props_free (cherokee_handler_avahi_props_t *props) cherokee_buffer_mrproper(&props->service_type); cherokee_avl_mrproper (&props->entries, (cherokee_func_free_t) cherokee_buffer_mrproper); -// cherokee_avl_mrproper (&props->entries, NULL); return cherokee_module_props_free_base (MODULE_PROPS(props)); } @@ -83,7 +82,7 @@ cherokee_handler_avahi_configure (cherokee_config_node_t *conf, cherokee_server_ CHEROKEE_NEW_STRUCT (n, handler_avahi_props); cherokee_module_props_init_base (MODULE_PROPS(n), - MODULE_PROPS_FREE(props_free)); + MODULE_PROPS_FREE(cherokee_handler_avahi_props_free)); /* Look at handler_avahi.h * This is an avahi of configuration. @@ -360,7 +359,7 @@ static void browse_callback( switch (event) { case AVAHI_BROWSER_FAILURE: TRACE("avahi", "(Browser) %s\n", avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b)))); - avahi_threaded_poll_stop(PROP_AVAHI(userdata)->threaded_poll); +// avahi_threaded_poll_stop(PROP_AVAHI(userdata)->threaded_poll); return; case AVAHI_BROWSER_NEW: @@ -406,7 +405,7 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void * userd if (state == AVAHI_CLIENT_FAILURE) { TRACE("avahi", "Server connection failure: %s\n", avahi_strerror(avahi_client_errno(c))); - avahi_threaded_poll_stop(PROP_AVAHI(userdata)->threaded_poll); +// avahi_threaded_poll_stop(PROP_AVAHI(userdata)->threaded_poll); } } diff --git a/handler_clusterstats.c b/handler_clusterstats.c index eca8b41..351a281 100644 --- a/handler_clusterstats.c +++ b/handler_clusterstats.c @@ -66,7 +66,6 @@ props_free (cherokee_handler_clusterstats_props_t *props) cherokee_buffer_mrproper(&props->service_type); cherokee_avl_mrproper (&props->entries, (cherokee_func_free_t) cherokee_buffer_mrproper); -// cherokee_avl_mrproper (&props->entries, NULL); return cherokee_module_props_free_base (MODULE_PROPS(props)); } @@ -107,10 +106,6 @@ cherokee_handler_clusterstats_configure (cherokee_config_node_t *conf, cherokee_ if (equal_buf_str (&subconf->key, "service_type")) { cherokee_buffer_add_buffer (&props->service_type, &subconf->val); } -/* else { - PRINT_MSG ("ERROR: Handler file: Unknown key: '%s'\n", subconf->key.buf); - return ret_error; - }*/ } /* If the configuration for avahi was not set, we should not continue */ diff --git a/handler_virt.c b/handler_virt.c index f3ac5f1..4f67809 100644 --- a/handler_virt.c +++ b/handler_virt.c @@ -84,6 +84,17 @@ #include #include #include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include /* Plug-in initialization @@ -104,10 +115,10 @@ PLUGIN_INFO_HANDLER_EASIEST_INIT (virt, http_get | http_post); static ret_t props_free (cherokee_handler_virt_props_t *props) { - cherokee_buffer_mrproper(&props->xsl); cherokee_buffer_mrproper(&props->virt); - return cherokee_module_props_free_base (MODULE_PROPS(props)); + + return cherokee_handler_avahi_props_free (PROP_AVAHI(props)); } @@ -162,6 +173,154 @@ cherokee_handler_virt_configure (cherokee_config_node_t *conf, cherokee_server_t return cherokee_handler_avahi_configure (conf, srv, _props); } +static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata) { + switch (state) { + case AVAHI_ENTRY_GROUP_ESTABLISHED : + /* The entry group has been established successfully */ + break; + + case AVAHI_ENTRY_GROUP_COLLISION : { + /* A service name collision with a remote service + * happened. */ + break; + } + + case AVAHI_ENTRY_GROUP_FAILURE : + /* Some kind of failure happened while we were registering our services */ + break; + + case AVAHI_ENTRY_GROUP_UNCOMMITED: + case AVAHI_ENTRY_GROUP_REGISTERING: + ; + } +} + +static void tender_resolve_callback( + AvahiServiceResolver *r, + AVAHI_GCC_UNUSED AvahiIfIndex interface, + AVAHI_GCC_UNUSED AvahiProtocol protocol, + AvahiResolverEvent event, + const char *name, + const char *type, + const char *domain, + const char *host_name, + const AvahiAddress *address, + uint16_t port, + AvahiStringList *txt, + AvahiLookupResultFlags flags, + void* userdata) { + + tender_t *tender = userdata; + + assert(r); + + /* Called whenever a service has been resolved successfully or timed out */ + + switch (event) { + case AVAHI_RESOLVER_FAILURE: + avahi_service_resolver_free(r); + break; + + case AVAHI_RESOLVER_FOUND: { + char a[AVAHI_ADDRESS_STR_MAX], *t; + AvahiStringList *needle; + + fprintf(stderr, "(Resolver) Service '%s' of type '%s' in domain '%s':\n", name, type, domain); + + avahi_address_snprint(a, sizeof(a), address); + t = avahi_string_list_to_string(txt); + fprintf(stderr, + "\t%s:%u (%s)\n" + "\tTXT=%s\n" + "\tcookie is %u\n" + "\tis_local: %i\n" + "\tour_own: %i\n" + "\twide_area: %i\n" + "\tmulticast: %i\n" + "\tcached: %i\n", + host_name, port, a, + t, + avahi_string_list_get_service_cookie(txt), + !!(flags & AVAHI_LOOKUP_RESULT_LOCAL), + !!(flags & AVAHI_LOOKUP_RESULT_OUR_OWN), + !!(flags & AVAHI_LOOKUP_RESULT_WIDE_AREA), + !!(flags & AVAHI_LOOKUP_RESULT_MULTICAST), + !!(flags & AVAHI_LOOKUP_RESULT_CACHED)); + + + avahi_free(t); + + unsigned int len = strlen(tender->name); + + if (strlen(name) > len && name[len] == '.' && strncmp(tender->name, name, len) == 0) { + if ((needle = avahi_string_list_find (txt, "cost")) != NULL) { + + float amount; + char *cost; + avahi_string_list_get_pair (needle, NULL, &cost, NULL); + amount = atof(cost); + + TRACE("tender", "%s will run %s for the cost of L$W %f\n", host_name, tender->name, amount); + if (amount < tender->cost) { + /* TODO: LOCK */ + tender->cost = amount; + tender->dom = strdup(host_name); + TRACE("tender", "We will consider his offer!"); + } + + avahi_free(cost); + } + break; + } + } + } +} + + +static void tender_browse_callback( + AvahiServiceBrowser *b, + AvahiIfIndex interface, + AvahiProtocol protocol, + AvahiBrowserEvent event, + const char *name, + const char *type, + const char *domain, + AVAHI_GCC_UNUSED AvahiLookupResultFlags flags, + void* userdata) { + + assert(b); + AvahiClient *c = avahi_service_browser_get_client(b); + + /* Called whenever a new services becomes available on the LAN or is removed from the LAN */ + + switch (event) { + case AVAHI_BROWSER_FAILURE: + fprintf(stderr, "(Browser) %s\n", avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b)))); + return; + + case AVAHI_BROWSER_NEW: + fprintf(stderr, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain); + + /* We ignore the returned resolver object. In the callback + function we free it. If the server is terminated before + the callback function is called the server will free + the resolver for us. */ + + if (!(avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, tender_resolve_callback, userdata))) + fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(c))); + + break; + + case AVAHI_BROWSER_REMOVE: + fprintf(stderr, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", name, type, domain); + break; + + case AVAHI_BROWSER_ALL_FOR_NOW: + case AVAHI_BROWSER_CACHE_EXHAUSTED: + fprintf(stderr, "(Browser) %s\n", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW"); + break; + } +} ret_t cherokee_handler_virt_init (cherokee_handler_virt_t *hdl) @@ -751,11 +910,68 @@ virt_virt_function(cherokee_handler_virt_t *hdl, virDomainPtr dom, virConnectPtr case domainCreate: { cherokee_buffer_t xmlDesc = CHEROKEE_BUF_INIT; + char txt[254]; save_xml(hdl, dom, &xmlDesc); - // TODO: conn = waar moet ik van avahi naar toe + tender_t best_tender; + snprintf(txt, 254, "memory=%lu", virDomainGetMaxMemory(dom)); + txt[253] = '\0'; + + best_tender.name = virDomainGetName(dom); + best_tender.cost = FLT_MAX; + best_tender.dom = NULL; + + AvahiServiceBrowser *sb = avahi_service_browser_new(HDL_AVAHI_PROPS(hdl)->client, AVAHI_IF_UNSPEC, + AVAHI_PROTO_UNSPEC, "_tender._tcp", + NULL, 0, tender_browse_callback, &best_tender); + + if (sb == NULL) { + TRACE("avahi", "For whatever reason the sb is NULL\n"); + } else { + + AvahiEntryGroup *group = avahi_entry_group_new(HDL_AVAHI_PROPS(hdl)->client, entry_group_callback, NULL); - cherokee_buffer_add_long10(buf, (virDomainUndefine(dom) == 0 && - (dom = virDomainCreateLinux(virConn, xmlDesc.buf, 0)) != NULL ? 0 : -1) ); + if (group == NULL) { + TRACE("avahi", "For whatever reason the group is NULL\n"); + } else { + avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, + best_tender.name, "_offer._tcp", NULL, NULL, 651, txt, NULL, NULL); + avahi_entry_group_commit(group); + + sleep(3); /* we are for quick bidding ;) */ + + avahi_entry_group_free(group); + } + + avahi_service_browser_free(sb); + + if (best_tender.dom == NULL) { + TRACE("virt", "Nobody wants %s, poor vm!\n", best_tender.name); + cherokee_buffer_add_long10(buf, -1); + } else { + if (virDomainUndefine(dom) != 0) { + TRACE("virt", "Can't undefine %s, some idiot run it already?\n", best_tender.name); + cherokee_buffer_add_long10(buf, -1); + } else { + cherokee_buffer_t uri = CHEROKEE_BUF_INIT; + virConnectClose(virConn); + cherokee_buffer_add_va (&uri, "xen://%s/", best_tender.dom); + virConn = virConnectOpen (uri.buf); + if (virConn == NULL) { + TRACE("virt", "Can't connect to %s\n", uri.buf); + cherokee_buffer_add_long10(buf, -1); + } else { + cherokee_buffer_add_long10(buf, + (virDomainCreateLinux(virConn, xmlDesc.buf, 0) != NULL ? + 0 : -1 )); + } + cherokee_buffer_mrproper(&uri); + } + TRACE("virt", "going to free\n"); + free(best_tender.dom); + } + + } + cherokee_buffer_mrproper(&xmlDesc); break; } @@ -1374,19 +1590,21 @@ virt_build_page (cherokee_handler_virt_t *hdl) cherokee_buffer_add_va (&hdl->buffer, "\n\n", HDL_VIRT_PROPS(hdl)->xsl.buf); - /* First, block the event loop */ - avahi_threaded_poll_lock(HDL_AVAHI_PROPS(hdl)->threaded_poll); switch (hdl->action) { case showall: cherokee_buffer_add_str (&hdl->buffer, ""); + avahi_threaded_poll_lock(HDL_AVAHI_PROPS(hdl)->threaded_poll); cherokee_avl_while(&HDL_AVAHI_PROPS(hdl)->entries, virt_while, hdl, NULL, NULL); + avahi_threaded_poll_unlock(HDL_AVAHI_PROPS(hdl)->threaded_poll); cherokee_buffer_add_str (&hdl->buffer, ""); ret = ret_ok; break; case showuservms: { cherokee_buffer_add_str (&hdl->buffer, ""); + avahi_threaded_poll_lock(HDL_AVAHI_PROPS(hdl)->threaded_poll); cherokee_avl_while(&HDL_AVAHI_PROPS(hdl)->entries, virt_while_user, hdl, NULL, NULL); + avahi_threaded_poll_unlock(HDL_AVAHI_PROPS(hdl)->threaded_poll); cherokee_buffer_add_str (&hdl->buffer, ""); ret = ret_ok; break; @@ -1395,7 +1613,10 @@ virt_build_page (cherokee_handler_virt_t *hdl) default: { cherokee_buffer_t *hostname = NULL; cherokee_buffer_add_va (&domu, "%s_%s", hdl->user.buf, hdl->vm.buf); + + avahi_threaded_poll_lock(HDL_AVAHI_PROPS(hdl)->threaded_poll); ret = cherokee_avl_get_ptr(&HDL_AVAHI_PROPS(hdl)->entries, domu.buf, (void **) &hostname); + avahi_threaded_poll_unlock(HDL_AVAHI_PROPS(hdl)->threaded_poll); if (ret == ret_not_found) { virDomainPtr virDom; @@ -1464,8 +1685,6 @@ virt_build_page (cherokee_handler_virt_t *hdl) } } - /* Finally, unblock the event loop */ - avahi_threaded_poll_unlock(HDL_AVAHI_PROPS(hdl)->threaded_poll); if (ret == ret_ok && hdl->action != showall && hdl->action != showuservms) { ret = virt_virt_do(hdl, &domu, &uri); diff --git a/handler_virt.h b/handler_virt.h index b909f95..6ed8a0c 100644 --- a/handler_virt.h +++ b/handler_virt.h @@ -99,6 +99,12 @@ typedef struct { } action; } cherokee_handler_virt_t; +typedef struct { + const char *name; + char *dom; + float cost; +} tender_t; + #define HDL_VIRT(x) ((cherokee_handler_virt_t *)(x)) #define PROP_VIRT(x) ((cherokee_handler_virt_props_t *)(x)) #define HDL_VIRT_PROPS(x) (PROP_VIRT(MODULE(x)->props)) -- 2.11.4.GIT