1 #include <avahi-client/publish.h>
2 #include <avahi-client/lookup.h>
4 #include <avahi-common/alternative.h>
5 #include <avahi-common/simple-watch.h>
6 #include <avahi-common/malloc.h>
7 #include <avahi-common/error.h>
8 #include <avahi-common/timeval.h>
9 #include <avahi-common/strlst.h>
10 #include <avahi-common/thread-watch.h>
12 #include <libvirt/libvirt.h>
17 unsigned int domainid
;
18 AvahiEntryGroup
*group
;
22 typedef struct list_el domu
;
24 domu
* domus
= NULL
; /* list of domains */
25 unsigned int domu_count
= 0;
28 static AvahiStringList
* domainProperties(virDomainPtr thisDomain
) {
29 AvahiStringList
*new = NULL
;
30 // avahi_string_list_new_from_array (NULL, 0);
32 virDomainInterfaceStatsStruct stats
;
33 virDomainGetInfo(thisDomain
, &info
);
34 new = avahi_string_list_add_printf(new, "maxMem=%lu", info
.maxMem
);
35 new = avahi_string_list_add_printf(new, "memory=%lu", info
.memory
);
36 new = avahi_string_list_add_printf(new, "cpuTime=%llu", info
.cpuTime
);
38 /* TODO: multiple network interfaces :( */
40 snprintf(vifname
, 14, "vif%d.0", virDomainGetID(thisDomain
));
44 virDomainInterfaceStats(thisDomain
, vifname
, &stats
, sizeof(stats
));
46 new = avahi_string_list_add_printf(new, "interfaces=eth%d", no
);
47 new = avahi_string_list_add_printf(new, "interface_eth%d_rxbytes=%lld", no
, stats
.rx_bytes
);
48 new = avahi_string_list_add_printf(new, "interface_eth%d_rxpackets=%lld", no
, stats
.rx_packets
);
49 // new = avahi_string_list_add_printf(new, "interface_eth%d_rxerrs=%lld", no, stats.rx_errs);
50 // new = avahi_string_list_add_printf(new, "interface_eth%d_rxdrop=%lld", no, stats.rx_drop);
51 new = avahi_string_list_add_printf(new, "interface_eth%d_txbytes=%lld", no
, stats
.tx_bytes
);
52 new = avahi_string_list_add_printf(new, "interface_eth%d_txpackets=%lld", no
, stats
.tx_packets
);
53 // new = avahi_string_list_add_printf(new, "interface_eth%d_txerrs=%lld", no, stats.tx_errs);
54 // new = avahi_string_list_add_printf(new, "interface_eth%d_txdrop=%lld", no, stats.tx_drop);
59 void remove_everything() {
62 for (i
= 0; i
< domu_count
; i
++) {
64 avahi_entry_group_free(domus
[i
].group
);
65 domus
[i
].group
= NULL
;
74 void migrate_everything() {
77 conn
= virConnectOpen(NULL
);
81 AvahiThreadedPoll
*threaded_poll
= NULL
;
82 AvahiClient
*client
= NULL
;
84 if ((threaded_poll
= avahi_threaded_poll_new())) {
85 if ((client
= avahi_client_new(avahi_threaded_poll_get(threaded_poll
), 0, NULL
, NULL
, NULL
)))
86 avahi_threaded_poll_start(threaded_poll
);
89 for (i
= 0; i
< domu_count
; i
++) {
91 dom
= virDomainLookupByID (conn
, domus
[i
].domainid
);
94 if (client
== NULL
|| migrate_domain(client
, threaded_poll
, dom
) != 0) {
95 virDomainShutdown(dom
);
105 avahi_threaded_poll_stop(threaded_poll
);
106 avahi_client_free(client
);
109 avahi_threaded_poll_free(threaded_poll
);
112 virConnectClose(conn
);
117 static void entry_group_callback_publish(AvahiEntryGroup
*g
, AvahiEntryGroupState state
, void *userdata
) {
118 domu
*this = userdata
;
121 case AVAHI_ENTRY_GROUP_ESTABLISHED
:
125 case AVAHI_ENTRY_GROUP_FAILURE
:
126 case AVAHI_ENTRY_GROUP_COLLISION
:
127 fprintf(stderr
, "Collision\n");
128 avahi_entry_group_free(g
);
138 void create_services(AvahiClient
*c
) {
139 virConnectPtr conn
= virConnectOpenReadOnly(NULL
);
142 int maxid
= virConnectNumOfDomains(conn
);
143 if (maxid
> 1) { /* ignore dom0 */
144 int *ids
= (int *) malloc(sizeof(int) * maxid
);
145 if ((maxid
= virConnectListDomains(conn
, &ids
[0], maxid
)) < 0) {
149 unsigned int domu_count_new
= (maxid
- 1);
150 domu
* domus_old
= domus
;
151 domus
= (domu
*) malloc(sizeof(domu
) * domu_count_new
);
152 const char *type
= "_domu._tcp";
154 for (i
= 0; i
< domu_count_new
; i
++) {
156 domus
[i
].group
= NULL
;
157 domus
[i
].domainid
= ids
[i
+1];
160 // fprintf(stderr, "Looking for %d\n", domus[i].domainid);
162 for (j
= 0; j
< domu_count
; j
++) {
163 // fprintf(stderr, "--> %d\n", domus_old[j].domainid);
164 if (ids
[i
+1] == domus_old
[j
].domainid
) {
165 // fprintf(stderr, "got it\n");
166 virDomainPtr thisDomain
= virDomainLookupByID(conn
, domus
[i
].domainid
);
169 name
= virDomainGetName(thisDomain
);
170 if (name
&& domus_old
[j
].group
) {
171 domus
[i
].group
= domus_old
[j
].group
;
172 AvahiStringList
*domainProps
;
173 domainProps
= domainProperties(thisDomain
);
174 domus_old
[j
].keep
= 1;
175 avahi_entry_group_update_service_txt_strlst(domus
[i
].group
, AVAHI_IF_UNSPEC
, AVAHI_PROTO_UNSPEC
, 0, name
, type
, NULL
, domainProps
);
176 avahi_string_list_free(domainProps
);
178 virDomainFree(thisDomain
);
182 if (i
> domu_count
|| domus
[i
].group
== NULL
) {
184 AvahiStringList
*domainProps
;
185 virDomainPtr thisDomain
= virDomainLookupByID(conn
, ids
[i
+1]);
187 AvahiEntryGroup
*group
;
188 group
= avahi_entry_group_new(c
, entry_group_callback_publish
, &domus
[i
]);
189 domainProps
= domainProperties(thisDomain
);
190 name
= virDomainGetName(thisDomain
);
193 avahi_entry_group_add_service_strlst(group
, AVAHI_IF_UNSPEC
, AVAHI_PROTO_UNSPEC
, 0, name
, type
, NULL
, NULL
, 651, domainProps
);
194 avahi_entry_group_commit(group
);
200 avahi_string_list_free(domainProps
);
201 virDomainFree(thisDomain
);
206 for (i
= 0; i
< domu_count
; i
++) {
207 // fprintf(stderr, "id: %d, keep: %d\n", domus_old[i].domainid, domus_old[i].keep);
208 if (domus_old
[i
].keep
== 0 && domus_old
[i
].group
!= NULL
) {
209 avahi_entry_group_free(domus_old
[i
].group
);
210 domus_old
[i
].group
= NULL
;
215 domu_count
= domu_count_new
;
221 virConnectClose(conn
);
222 //fprintf(stderr, "exit: %s\n", __func__);