Interesting information inside
[handlervirt.git] / domumdns.c
blob183aec4e03f69307e77a9d66393f73c3242d07d2
1 #include <time.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <assert.h>
6 #include <avahi-client/client.h>
7 #include <avahi-client/publish.h>
9 #include <avahi-common/alternative.h>
10 #include <avahi-common/simple-watch.h>
11 #include <avahi-common/malloc.h>
12 #include <avahi-common/error.h>
13 #include <avahi-common/timeval.h>
15 #include <libvirt/libvirt.h>
17 #define POLL 5
19 struct list_el {
20 unsigned int domainid;
21 AvahiEntryGroup *group;
22 unsigned short keep;
25 typedef struct list_el domu;
27 domu * domus = NULL; /* list of domains */
28 unsigned int domu_count = 0;
29 static AvahiSimplePoll *simple_poll = NULL;
31 static AvahiStringList * domainProperties(virDomainPtr thisDomain) {
32 AvahiStringList *new = avahi_string_list_new(NULL);
33 virDomainInfo info;
34 virDomainGetInfo(thisDomain, &info);
35 new = avahi_string_list_add_printf(new, "maxMem=%lu", info.maxMem);
36 new = avahi_string_list_add_printf(new, "memory=%lu", info.memory);
37 new = avahi_string_list_add_printf(new, "cpuTime=%llu", info.cpuTime);
39 /* todo network, block device */
41 return new;
44 static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata) {
45 /* Called whenever the entry group state changes */
47 switch (state) {
48 case AVAHI_ENTRY_GROUP_ESTABLISHED :
49 /* The entry group has been established successfully */
50 //fprintf(stderr, "Service '%s' successfully established.\n", name);
51 break;
53 case AVAHI_ENTRY_GROUP_COLLISION : {
54 // char *n;
56 /* A service name collision with a remote service
57 * happened. Let's pick a new name */
58 //n = avahi_alternative_service_name(name);
59 //avahi_free(name);
60 //name = n;
62 // fprintf(stderr, "Service name collision, renaming service to '%s'\n", name);
64 /* And recreate the services */
65 //create_services(avahi_entry_group_get_client(g));
66 break;
69 case AVAHI_ENTRY_GROUP_FAILURE :
71 fprintf(stderr, "Entry group failure: %s\n", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))));
73 /* Some kind of failure happened while we were registering our services */
74 avahi_simple_poll_quit(simple_poll);
75 break;
77 case AVAHI_ENTRY_GROUP_UNCOMMITED:
78 case AVAHI_ENTRY_GROUP_REGISTERING:
83 void create_services(AvahiClient *c) {
84 virConnectPtr conn = virConnectOpenReadOnly(NULL);
85 if (conn == NULL)
86 return;
87 int maxid = virConnectNumOfDomains(conn);
88 if (maxid > 1) { /* ignore dom0 */
89 int *ids = (int *) malloc(sizeof(int) * maxid);
90 if ((maxid = virConnectListDomains(conn, &ids[0], maxid)) < 0) {
91 // error
92 } else {
93 int i;
94 unsigned int domu_count_new = (maxid - 1);
95 domu * domus_old = domus;
96 domus = (domu *) malloc(sizeof(domu) * domu_count_new);
97 const char *type = "_domu._tcp";
98 for (i = 0; i < domu_count_new; i++) {
99 int j;
100 domus[i].group = NULL;
101 domus[i].domainid = ids[i+1];
102 domus[i].keep = 0;
104 for (j = 0; j < domu_count; j++) {
105 if (ids[i+1] == domus_old[j].domainid) {
106 virDomainPtr thisDomain = virDomainLookupByID(conn, domus[i].domainid);
107 AvahiStringList *domainProps;
108 domus[i].group = domus_old[j].group;
109 domus_old[j].keep = 1;
110 domainProps = domainProperties(thisDomain);
111 avahi_entry_group_update_service_txt_strlst(domus[i].group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, virDomainGetName(thisDomain), type, NULL, domainProps);
112 avahi_string_list_free(domainProps);
113 virDomainFree(thisDomain);
116 if (i > domu_count || domus[i].group == NULL) {
117 AvahiStringList *domainProps;
118 virDomainPtr thisDomain = virDomainLookupByID(conn, ids[i+1]);
119 domus[i].group = avahi_entry_group_new(c, entry_group_callback, NULL);
120 domainProps = domainProperties(thisDomain);
121 avahi_entry_group_add_service_strlst(domus[i].group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, virDomainGetName(thisDomain), type, NULL, NULL, 651, domainProps);
122 avahi_string_list_free(domainProps);
123 virDomainFree(thisDomain);
124 avahi_entry_group_commit(domus[i].group);
129 for (i = 0; i < domu_count; i++) {
130 if (domus_old[i].keep == 0 && domus_old[i].group != NULL) {
131 avahi_entry_group_free(domus_old[i].group);
135 free(domus_old);
136 domu_count = domu_count_new;
138 free(ids);
140 virConnectClose(conn);
144 static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
145 assert(c);
147 /* Called whenever the client or server state changes */
149 switch (state) {
150 case AVAHI_CLIENT_S_RUNNING:
152 /* The server has startup successfully and registered its host
153 * name on the network, so it's time to create our services */
154 create_services(c);
155 break;
157 case AVAHI_CLIENT_FAILURE:
159 fprintf(stderr, "Client failure: %s\n", avahi_strerror(avahi_client_errno(c)));
160 avahi_simple_poll_quit(simple_poll);
162 break;
164 case AVAHI_CLIENT_S_COLLISION:
166 /* Let's drop our registered services. When the server is back
167 * in AVAHI_SERVER_RUNNING state we will register them
168 * again with the new host name. */
170 case AVAHI_CLIENT_S_REGISTERING:
172 /* The server records are now being established. This
173 * might be caused by a host name change. We need to wait
174 * for our own records to register until the host name is
175 * properly esatblished. */
177 /* if (group)
178 avahi_entry_group_reset(group);*/
180 break;
182 case AVAHI_CLIENT_CONNECTING:
189 static void modify_callback(AvahiTimeout *e, void *userdata) {
190 struct timeval tv;
191 AvahiClient *client = userdata;
193 // fprintf(stderr, "Doing some weird modification\n");
195 /* If the server is currently running, we need to remove our
196 * service and create it anew */
197 if (avahi_client_get_state(client) == AVAHI_CLIENT_S_RUNNING) {
198 /* And create them again with the new name */
199 create_services(client);
201 avahi_simple_poll_get(simple_poll)->timeout_update(e, avahi_elapse_time(&tv, 1000*POLL, 0));
204 int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
205 AvahiClient *client = NULL;
206 int error;
207 int ret = 1;
208 struct timeval tv;
209 /* Allocate main loop object */
210 if (!(simple_poll = avahi_simple_poll_new())) {
211 fprintf(stderr, "Failed to create simple poll object.\n");
212 goto fail;
215 /* Allocate a new client */
216 client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0, client_callback, NULL, &error);
218 /* Check wether creating the client object succeeded */
219 if (!client) {
220 fprintf(stderr, "Failed to create client: %s\n", avahi_strerror(error));
221 goto fail;
224 /* After 10s do some weird modification to the service */
225 avahi_simple_poll_get(simple_poll)->timeout_new(
226 avahi_simple_poll_get(simple_poll),
227 avahi_elapse_time(&tv, 1000*POLL, 0),
228 modify_callback,
229 client);
231 /* Run the main loop */
232 avahi_simple_poll_loop(simple_poll);
234 ret = 0;
236 fail:
238 /* Cleanup things */
240 if (client)
241 avahi_client_free(client);
243 if (simple_poll)
244 avahi_simple_poll_free(simple_poll);
246 return ret;