And the files that actually handler the tender phase now.
[handlervirt.git] / domumdns.c
blob1b510e7e5b5c63ca9ac01a55a99e21768f369a33
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 virDomainInterfaceStatsStruct stats;
35 virDomainGetInfo(thisDomain, &info);
36 new = avahi_string_list_add_printf(new, "maxMem=%lu", info.maxMem);
37 new = avahi_string_list_add_printf(new, "memory=%lu", info.memory);
38 new = avahi_string_list_add_printf(new, "cpuTime=%llu", info.cpuTime);
40 /* TODO: multiple network interfaces :( */
41 char vifname[16];
42 snprintf(vifname, 14, "vif%d.0", virDomainGetID(thisDomain));
43 vifname[15] = '\0';
44 unsigned int no = 0;
46 virDomainInterfaceStats(thisDomain, vifname, &stats, sizeof(stats));
48 new = avahi_string_list_add_printf(new, "interfaces=eth%d", no);
49 new = avahi_string_list_add_printf(new, "interface_eth%d_rxbytes=%lld", no, stats.rx_bytes);
50 new = avahi_string_list_add_printf(new, "interface_eth%d_rxpackets=%lld", no, stats.rx_packets);
51 // new = avahi_string_list_add_printf(new, "interface_eth%d_rxerrs=%lld", no, stats.rx_errs);
52 // new = avahi_string_list_add_printf(new, "interface_eth%d_rxdrop=%lld", no, stats.rx_drop);
53 new = avahi_string_list_add_printf(new, "interface_eth%d_txbytes=%lld", no, stats.tx_bytes);
54 new = avahi_string_list_add_printf(new, "interface_eth%d_txpackets=%lld", no, stats.tx_packets);
55 // new = avahi_string_list_add_printf(new, "interface_eth%d_txerrs=%lld", no, stats.tx_errs);
56 // new = avahi_string_list_add_printf(new, "interface_eth%d_txdrop=%lld", no, stats.tx_drop);
58 return new;
61 static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata) {
62 /* Called whenever the entry group state changes */
64 switch (state) {
65 case AVAHI_ENTRY_GROUP_ESTABLISHED :
66 /* The entry group has been established successfully */
67 //fprintf(stderr, "Service '%s' successfully established.\n", name);
68 break;
70 case AVAHI_ENTRY_GROUP_COLLISION : {
71 // char *n;
73 /* A service name collision with a remote service
74 * happened. Let's pick a new name */
75 //n = avahi_alternative_service_name(name);
76 //avahi_free(name);
77 //name = n;
79 // fprintf(stderr, "Service name collision, renaming service to '%s'\n", name);
81 /* And recreate the services */
82 //create_services(avahi_entry_group_get_client(g));
83 break;
86 case AVAHI_ENTRY_GROUP_FAILURE :
88 fprintf(stderr, "Entry group failure: %s\n", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))));
90 /* Some kind of failure happened while we were registering our services */
91 avahi_simple_poll_quit(simple_poll);
92 break;
94 case AVAHI_ENTRY_GROUP_UNCOMMITED:
95 case AVAHI_ENTRY_GROUP_REGISTERING:
100 void create_services(AvahiClient *c) {
101 virConnectPtr conn = virConnectOpenReadOnly(NULL);
102 if (conn == NULL)
103 return;
104 int maxid = virConnectNumOfDomains(conn);
105 if (maxid > 1) { /* ignore dom0 */
106 int *ids = (int *) malloc(sizeof(int) * maxid);
107 if ((maxid = virConnectListDomains(conn, &ids[0], maxid)) < 0) {
108 // error
109 } else {
110 int i;
111 unsigned int domu_count_new = (maxid - 1);
112 domu * domus_old = domus;
113 domus = (domu *) malloc(sizeof(domu) * domu_count_new);
114 const char *type = "_domu._tcp";
115 for (i = 0; i < domu_count_new; i++) {
116 int j;
117 domus[i].group = NULL;
118 domus[i].domainid = ids[i+1];
119 domus[i].keep = 0;
121 //fprintf(stderr, "Looking for %d\n", domus[i].domainid);
123 for (j = 0; j < domu_count; j++) {
124 //fprintf(stderr, "--> %d\n", domus_old[j].domainid);
125 if (ids[i+1] == domus_old[j].domainid) {
126 //fprintf(stderr, "got it\n");
127 virDomainPtr thisDomain = virDomainLookupByID(conn, domus[i].domainid);
128 domus[i].group = domus_old[j].group;
129 if (thisDomain) {
130 const char *name = virDomainGetName(thisDomain);
131 if (name) {
132 AvahiStringList *domainProps;
133 domainProps = domainProperties(thisDomain);
134 domus_old[j].keep = 1;
135 avahi_entry_group_update_service_txt_strlst(domus[i].group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, name, type, NULL, domainProps);
136 avahi_string_list_free(domainProps);
137 } else {
138 // domus_old[j].keep = 0;
140 } else {
141 // domus_old[j].keep = 0;
143 virDomainFree(thisDomain);
146 if (i > domu_count || domus[i].group == NULL) {
147 const char *name;
148 AvahiStringList *domainProps;
149 virDomainPtr thisDomain = virDomainLookupByID(conn, ids[i+1]);
150 domus[i].group = avahi_entry_group_new(c, entry_group_callback, NULL);
151 domainProps = domainProperties(thisDomain);
152 name = virDomainGetName(thisDomain);
154 if (name) {
155 avahi_entry_group_add_service_strlst(domus[i].group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, name, type, NULL, NULL, 651, domainProps);
156 avahi_entry_group_commit(domus[i].group);
157 } else {
158 domus[i].keep = 0;
161 avahi_string_list_free(domainProps);
162 virDomainFree(thisDomain);
167 for (i = 0; i < domu_count; i++) {
168 // fprintf(stderr, "id: %d, keep: %d\n", domus_old[i].domainid, domus_old[i].keep);
169 if (domus_old[i].keep == 0 && domus_old[i].group != NULL) {
170 avahi_entry_group_free(domus_old[i].group);
174 free(domus_old);
175 domu_count = domu_count_new;
177 free(ids);
179 virConnectClose(conn);
180 //fprintf(stderr, "exit: %s\n", __func__);
183 static void modify_callback(AvahiTimeout *e, void *userdata) {
184 struct timeval tv;
185 AvahiClient *client = userdata;
187 /* If the server is currently running, we need to remove our
188 * service and create it anew */
189 if (avahi_client_get_state(client) == AVAHI_CLIENT_S_RUNNING) {
190 /* And create them again with the new name */
191 create_services(client);
193 avahi_simple_poll_get(simple_poll)->timeout_update(e, avahi_elapse_time(&tv, 1000*POLL, 0));
197 static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
199 /* Called whenever the client or server state changes */
201 switch (state) {
202 case AVAHI_CLIENT_S_RUNNING: {
203 /* The server has startup successfully and registered its host
204 * name on the network, so it's time to create our services */
206 struct timeval tv;
207 /* After 10s do some weird modification to the service */
208 avahi_simple_poll_get(simple_poll)->timeout_new(
209 avahi_simple_poll_get(simple_poll),
210 avahi_elapse_time(&tv, 1000*POLL, 0),
211 modify_callback,
214 break;
217 case AVAHI_CLIENT_FAILURE: {
218 int error;
219 AvahiClient *client = NULL;
221 if (c)
222 avahi_client_free(c);
224 /* Allocate a new client */
225 client = avahi_client_new(avahi_simple_poll_get(simple_poll), AVAHI_CLIENT_NO_FAIL, client_callback, NULL, &error);
227 /* Check wether creating the client object succeeded */
228 if (!client) {
229 /* If you look at the above argument, this should NEVER
230 happen */
231 fprintf(stderr, "Failed to create client: %s\n", avahi_strerror(error));
232 avahi_simple_poll_quit(simple_poll);
235 break;
238 case AVAHI_CLIENT_S_COLLISION:
240 /* Let's drop our registered services. When the server is back
241 * in AVAHI_SERVER_RUNNING state we will register them
242 * again with the new host name. */
244 case AVAHI_CLIENT_S_REGISTERING:
246 /* The server records are now being established. This
247 * might be caused by a host name change. We need to wait
248 * for our own records to register until the host name is
249 * properly esatblished. */
251 break;
253 case AVAHI_CLIENT_CONNECTING:
260 int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
261 int ret = 1;
262 /* Allocate main loop object */
263 if (!(simple_poll = avahi_simple_poll_new())) {
264 fprintf(stderr, "Failed to create simple poll object.\n");
265 goto fail;
268 client_callback(NULL, AVAHI_CLIENT_FAILURE, NULL);
270 /* Run the main loop */
271 avahi_simple_poll_loop(simple_poll);
273 ret = 0;
275 fail:
276 /* Cleanup things */
277 if (simple_poll)
278 avahi_simple_poll_quit(simple_poll);
280 if (simple_poll)
281 avahi_simple_poll_free(simple_poll);
283 if (domus)
284 free(domus);
286 return ret;