Kernelcmdline, end for rrd
[handlervirt.git] / handler_virt.c
blob338cdc71d055a8805d767fa1ea5f0f376136406a
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 /* Cherokee
5 * Authors:
6 * Alvaro Lopez Ortega <alvaro@alobbs.com>
7 * Stefan de Konink <stefan@konink.de>
9 * Copyright (C) 2001-2008 Alvaro Lopez Ortega
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of version 2 of the GNU General Public
13 * License as published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 * USA
26 // #define LINUX_CMDLINE "root=/dev/xvda ro ip=%s:1.2.3.4:%s:%s::eth0:off"
28 #define VIRT_INTERFACE_XML \
29 " <interface type='bridge'>" \
30 " <source bridge='xenbr0'/>" \
31 " <mac address='%s'/>" \
32 " <ip address='%s' />" \
33 " <script path='vif-bridge'/>" \
34 " </interface>"
36 //" <target dev='vif1.0'/>" \
38 #define VIRT_DISK_XML \
39 " <disk type='file' device='disk'>" \
40 " <driver name='tap' type='aio' />" \
41 " <source file='%s'/>" \
42 " <target dev='%s' bus='xen'/>" \
43 " </disk>"
45 #define VIRT_DOMAIN_CMD_IP "ip=%s:1.2.3.4:%s:255.255.255.0::eth0:off"
47 #define VIRT_DOMAIN_XML \
48 "<domain type='xen'>" \
49 " <name>%s_%s</name>" \
50 " <os>" \
51 " <type>linux</type>" \
52 " <kernel>/usr/lib/xen/boot/linux-2.6.20-xen-r6</kernel>" \
53 " <cmdline> root=/dev/xvda ro %s</cmdline>" \
54 " </os>" \
55 " <memory>%d</memory>" \
56 " <vcpu>%d</vcpu>" \
57 " <on_poweroff>destroy</on_poweroff>" \
58 " <on_reboot>restart</on_reboot>" \
59 " <on_crash>destroy</on_crash>" \
60 " <devices>" \
61 " %s" \
62 " </devices>" \
63 "</domain>"
65 #define VIRT_STORAGE_XML \
66 "<volume type='%s'>" \
67 " <name>%s_%s</name>" \
68 " <allocation>%lu</allocation>" \
69 " <capacity unit='%s'>%lu</capacity>" \
70 " <target>" \
71 " <path>%s_%s</path>" \
72 " <permissions>" \
73 " <owner>0744</owner>" \
74 " <group>0744</group>" \
75 " <mode>0744</mode>" \
76 " <label>%s_%s</label>" \
77 " </permissions>" \
78 " </target>" \
79 "</volume>"
82 #include "handler_virt.h"
83 #include "handler_avahi.h"
84 #include <cherokee/cherokee.h>
85 #include <libxml/parser.h>
86 #include <libxml/xpath.h>
89 /* Plug-in initialization
91 * In this function you can use any of these:
92 * http_delete | http_get | http_post | http_put
94 * For a full list: cherokee_http_method_t
96 * It is what your handler to be implements.
99 PLUGIN_INFO_HANDLER_EASIEST_INIT (virt, http_get | http_post);
102 /* Methods implementation
104 static ret_t
105 props_free (cherokee_handler_virt_props_t *props)
108 cherokee_buffer_mrproper(&props->xsl);
109 cherokee_buffer_mrproper(&props->virt);
110 return cherokee_module_props_free_base (MODULE_PROPS(props));
114 ret_t
115 cherokee_handler_virt_configure (cherokee_config_node_t *conf, cherokee_server_t *srv, cherokee_module_props_t **_props)
117 cherokee_list_t *i;
118 cherokee_handler_virt_props_t *props;
120 /* Instance a new property object
123 if (*_props == NULL) {
124 CHEROKEE_NEW_STRUCT (n, handler_virt_props);
126 cherokee_handler_avahi_props_init_base (PROP_AVAHI(n), MODULE_PROPS_FREE(props_free));
128 /* Look at handler_virt.h
129 * This is an virt of configuration.
131 n->authenticate = true; /* by default we are secure! */
132 n->read_only = true; /* by default we are secure! */
133 cherokee_buffer_init (&n->xsl); /* we support a custom header */
134 cherokee_buffer_init (&n->virt); /* your first xenserver */
136 *_props = MODULE_PROPS(n);
139 props = PROP_VIRT(*_props);
141 cherokee_config_node_foreach (i, conf) {
142 cherokee_config_node_t *subconf = CONFIG_NODE(i);
144 if (equal_buf_str (&subconf->key, "authenticate")) {
145 props->authenticate = atoi(subconf->val.buf);
147 else if (equal_buf_str (&subconf->key, "read_only")) {
148 props->read_only = atoi(subconf->val.buf);
150 else if (equal_buf_str (&subconf->key, "xsl")) {
151 cherokee_buffer_add_buffer (&props->xsl, &subconf->val);
153 else if (equal_buf_str (&subconf->key, "virt")) {
154 cherokee_buffer_add_buffer (&props->virt, &subconf->val);
159 /* Init base class
162 return cherokee_handler_avahi_configure (conf, srv, _props);
166 ret_t
167 cherokee_handler_virt_init (cherokee_handler_virt_t *hdl)
169 int isroot = false;
170 int len;
171 char *this, *next;
173 cherokee_connection_t *conn = HANDLER_CONN(hdl);
174 cherokee_buffer_init(&hdl->user);
175 cherokee_buffer_init(&hdl->vm);
177 hdl->action = nothing;
179 cherokee_buffer_add (&conn->pathinfo,
180 conn->request.buf + conn->web_directory.len,
181 conn->request.len - conn->web_directory.len);
183 this = conn->pathinfo.buf + 1;
184 next = strchr(this, '/');
187 if ((!next && (this && (len = strlen(this)) == 0)) || (next && ((len = next - this) == 0)) )
188 hdl->action = showall;
189 else {
190 cherokee_buffer_add (&hdl->user, this, len);
193 if (HDL_VIRT_PROPS(hdl)->authenticate) {
194 if (!conn->validator ||
195 (conn->validator &&
196 (!cherokee_buffer_cmp_buf(&conn->validator->user, &hdl->user) &&
197 !(isroot = cherokee_buffer_cmp (&conn->validator->user, "root", 4))))) {
198 hdl->action = nothing; /* just in case */
199 conn->error_code = http_unauthorized;
200 return ret_error;
202 } else {
203 isroot = true;
206 if (hdl->action == showall) {
207 if (!isroot) {
208 hdl->action = nothing;
209 conn->error_code = http_unauthorized;
210 return ret_error;
211 } else {
212 return virt_build_page(hdl);
217 if (!next) {
218 hdl->action = showuservms;
219 return virt_build_page(hdl);
220 } else {
221 this = next + 1;
222 next = strchr(this, '/');
224 if ( ( !next && (this && (len = strlen(this)) == 0) ) || (next && ((len = next - this) == 0)) ) {
225 //if (!next && (this && (len = strlen(this)) == 0) || (next && ((len = next - this) == 0)) ) {
226 hdl->action = showuservms;
227 return virt_build_page(hdl);
231 cherokee_buffer_add (&hdl->vm, this, len);
233 if (!next) {
234 hdl->action = domainGetXMLDesc;
235 return virt_build_page(hdl);
236 } else {
237 this = next + 1;
238 next = strchr(this, '/');
240 if (( !next && (this && (len = strlen(this)) == 0) ) || (next && ((len = next - this) == 0)) ) {
241 hdl->action = domainGetXMLDesc;
242 return virt_build_page(hdl);
246 /* TODO: it would be nice to filter read_only methods already on this point */
247 hdl->action = not_implemented;
248 switch (conn->header.method) {
249 case http_get:
250 if (strncmp(this, "virDomain", 9) == 0) {
251 if (strncmp(this+9, "Get", 3) == 0) {
252 if (strcmp(this+12, "ID") == 0) hdl->action = domainGetID;
253 else if (strcmp(this+12, "Name") == 0) hdl->action = domainGetName;
254 else if (strcmp(this+12, "MaxMemory") == 0) hdl->action = domainGetMaxMemory;
255 else if (strcmp(this+12, "MaxVcpus") == 0) hdl->action = domainGetMaxVcpus;
256 else if (strcmp(this+12, "OSType") == 0) hdl->action = domainGetOSType;
257 else if (strcmp(this+12, "UUID") == 0) hdl->action = domainGetUUID;
258 else if (strcmp(this+12, "UUIDString") == 0) hdl->action = domainGetUUIDString;
259 else if (strcmp(this+12, "XMLDesc") == 0) hdl->action = domainGetXMLDesc;
262 else if (strcmp(this+9, "Create") == 0) hdl->action = domainCreate;
263 else if (strcmp(this+9, "Destroy") == 0) hdl->action = domainDestroy;
264 else if (strcmp(this+9, "Reboot") == 0) hdl->action = domainReboot;
265 else if (strcmp(this+9, "Shutdown") == 0) hdl->action = domainShutdown;
267 else if (strcmp(this+9, "Save") == 0) hdl->action = domainSave;
268 else if (strcmp(this+9, "Restore") == 0) hdl->action = domainRestore;
270 else if (strcmp(this+9, "AttachDevice") == 0) hdl->action = domainAttachDevice_args;
272 else if (strcmp(this+9, "DefineXML") == 0) hdl->action = domainDefineXML_args;
273 else if (strcmp(this+9, "Undefine") == 0) hdl->action = domainUndefine;
276 else if (strncmp(this, "virStorage", 10) == 0) {
277 if (strncmp(this+10, "Vol", 3) == 0) {
278 if (strcmp(this+13, "CreateXML") == 0) hdl->action = storageVolCreateXML_args;
279 else if (strcmp(this+13, "Delete") == 0) hdl->action = storageVolDelete_args;
280 else if (strcmp(this+13, "CloneXML") == 0) hdl->action = storageVolCloneXML_args;
281 else if (strcmp(this+13, "GetXMLDesc") == 0) hdl->action = storageVolGetXMLDesc_args;
282 else if (strcmp(this+13, "SetPassword") == 0) hdl->action = storageVolSetPassword_args;
285 else if (strncmp(this, "virGraph", 8) == 0) {
286 if (strcmp(this+8, "Load") == 0) hdl->action = graphLoad_args;
287 if (strcmp(this+8, "Interface") == 0) hdl->action = graphInterface_args;
289 break;
291 case http_post: {
292 off_t postl;
293 cherokee_post_get_len (&conn->post, &postl);
295 if (postl <= 0 || postl >= (INT_MAX-1)) {
296 TRACE("virt", "post without post");
297 conn->error_code = http_bad_request;
298 return ret_error;
301 if (strncmp(this, "virDomain", 9) == 0) {
302 if (strcmp(this+9, "AttachDevice") == 0) hdl->action = domainAttachDevice;
303 else if (strcmp(this+9, "DetachDevice") == 0) hdl->action = domainDetachDevice;
304 else if (strcmp(this+9, "DefineXML") == 0) hdl->action = domainDefineXML;
306 else if (strncmp(this, "virStorage", 10) == 0) {
307 if (strncmp(this+10, "Vol", 3) == 0) {
308 if (strcmp(this+13, "CreateXML") == 0) hdl->action = storageVolCreateXML;
312 break;
315 default:
316 return ret_error;
319 if (hdl->action <= 0) {
320 TRACE("virt", "There was no action specified");
321 conn->error_code = http_bad_request;
322 return ret_error;
326 return virt_build_page(hdl);
329 ret_t
330 cherokee_handler_virt_free (cherokee_handler_virt_t *hdl)
332 cherokee_buffer_mrproper (&hdl->buffer);
333 cherokee_buffer_mrproper (&hdl->user);
334 cherokee_buffer_mrproper (&hdl->vm);
336 return ret_ok;
339 ret_t
340 cherokee_handler_virt_step (cherokee_handler_virt_t *hdl, cherokee_buffer_t *buffer)
342 if (cherokee_buffer_is_empty (&hdl->buffer))
343 return ret_eof;
345 cherokee_buffer_add (buffer, hdl->buffer.buf, 1024);
346 cherokee_buffer_move_to_begin (&hdl->buffer, 1024);
348 if (cherokee_buffer_is_empty (&hdl->buffer))
349 return ret_eof_have_data;
351 return ret_ok;
354 ret_t
355 cherokee_handler_virt_add_headers (cherokee_handler_virt_t *hdl, cherokee_buffer_t *buffer)
357 cherokee_buffer_add_va (buffer, "Content-Length: %d"CRLF, hdl->buffer.len);
359 if (hdl->action > xml)
360 cherokee_buffer_add_str (buffer, "Content-Type: application/xml"CRLF);
361 else if (hdl->action > graph) {
362 cherokee_buffer_add_str (buffer, "Content-Type: image/png"CRLF);
363 } else
364 cherokee_buffer_add_str (buffer, "Content-Type: text/plain"CRLF);
366 return ret_ok;
370 static ret_t
371 while_func_entries (cherokee_buffer_t *key, void *value, void *param) {
372 virConnectPtr conn = NULL;
373 cherokee_buffer_t uri = CHEROKEE_BUF_INIT;
374 cherokee_buffer_t *buf = (cherokee_buffer_t *)param;
376 cherokee_buffer_add_va (&uri, "xen://%s/", value);
378 if (HDL_VIRT_PROPS(hdl)->read_only == FALSE && !(conn = virConnectOpen (uri.buf))) {
379 if (!(conn = virConnectOpen (uri.buf))) {
380 return ret_error;
384 if (!conn && !(conn = virConnectOpenReadOnly (uri.buf))) {
385 return ret_error;
386 } else {
387 virDomainPtr dom;
388 if (!(dom = virDomainLookupByName(conn, (const char *) key->buf))) {
389 return ret_error;
390 } else {
391 char *xml = virDomainGetXMLDesc(dom, 0);
392 cherokee_buffer_add(buf, xml, strlen(xml));
394 virConnectClose(conn);
397 cherokee_buffer_mrproper(&uri);
399 return ret_ok;
402 static ret_t save_xml(cherokee_handler_virt_t *hdl, virDomainPtr result, cherokee_buffer_t *buf) {
403 ret_t ret = ret_error;
404 FILE *fd;
405 cherokee_buffer_t path = CHEROKEE_BUF_INIT;
406 cherokee_buffer_add_va (&path, "/mnt/netapp/users/%s", hdl->user.buf);
408 mkdir(path.buf, 0755);
409 cherokee_buffer_add_va (&path, "/%s", hdl->vm.buf);
411 mkdir(path.buf, 0755);
412 cherokee_buffer_add_str (&path, "/index.xml");
414 if ((fd = fopen(path.buf, "w")) == NULL) {
415 perror(__func__);
416 } else {
417 char *output = virDomainGetXMLDesc(result, 0);
418 fwrite(output, strlen(output), sizeof(char), fd);
419 fclose(fd);
420 if (buf)
421 cherokee_buffer_add(buf, output, strlen(output));
422 free(output);
423 ret = ret_ok;
425 cherokee_buffer_mrproper(&path);
426 return ret;
430 static ret_t
431 virt_virt_function(cherokee_handler_virt_t *hdl, virDomainPtr dom, virConnectPtr virConn) {
432 cherokee_connection_t *conn = HANDLER_CONN(hdl);
433 cherokee_buffer_t *buf = &HDL_AVAHI(hdl)->buffer;
435 switch (hdl->action) {
436 /* Save the memory of a domain to a file and suspend the domain */
437 case domainSave: {
438 ret_t ret = ret_ok;
439 int result;
440 cherokee_buffer_t path = CHEROKEE_BUF_INIT;
441 cherokee_buffer_add_va (&path, "/mnt/netapp/users/%s/%s/memory", hdl->user.buf, hdl->vm.buf);
442 if ((result = virDomainSave(dom, path.buf)) != 0) {
443 TRACE("virt", "Saving of %s/%s failed", hdl->user.buf, hdl->vm.buf);
444 conn->error_code = http_internal_error;
445 ret = ret_error;
447 cherokee_buffer_mrproper(&path);
449 cherokee_buffer_add_long10(buf, result);
450 return ret;
451 break;
454 /* Restore the memory of a domain from a file and resume the domain */
455 case domainRestore: {
456 ret_t ret = ret_ok;
457 struct stat statbuf;
458 cherokee_buffer_t path = CHEROKEE_BUF_INIT;
459 cherokee_buffer_add_va (&path, "/mnt/netapp/users/%s/%s/memory", hdl->user.buf, hdl->vm.buf);
461 if (stat(path.buf, &statbuf) == 0) {
462 int result;
463 if ((result = virDomainRestore(virConn, path.buf)) != 0) {
464 TRACE("virt", "Restoring of %s/%s failed", hdl->user.buf, hdl->vm.buf);
465 conn->error_code = http_internal_error;
466 ret = ret_error;
468 cherokee_buffer_add_long10(buf, result);
469 } else {
470 TRACE("virt", "Memory file for %s/%s does not exist", hdl->user.buf, hdl->vm.buf);
471 conn->error_code = http_not_found;
472 ret = ret_error;
475 cherokee_buffer_mrproper(&path);
476 return ret;
477 break;
480 case domainUndefine: {
481 int result;
482 if ((result = virDomainUndefine(dom)) != 0) {
483 conn->error_code = http_internal_error; /* TODO */
486 cherokee_buffer_add_long10(buf, result);
487 break;
490 case domainAttachDevice_args: {
491 int result;
492 void *temp;
493 ret_t ret;
495 ret = cherokee_avl_get_ptr (conn->arguments, "type", &temp);
497 if (ret == ret_ok) {
498 cherokee_buffer_t xml = CHEROKEE_BUF_INIT;
500 if (strcmp(temp, "disk") == 0) {
501 void *device;
502 if ((ret = cherokee_avl_get_ptr (conn->arguments, "device", &device)) == ret_ok) {
503 void *file;
504 if ((ret = cherokee_avl_get_ptr (conn->arguments, "file", &file)) == ret_ok) {
505 cherokee_buffer_add_va (&xml, VIRT_DISK_XML, file, device);
506 } else {
507 virStorageVolPtr volume = virt_get_vol_by_args(hdl, virConn, 1);
509 if (volume == NULL) {
510 return ret_error;
513 file = virStorageVolGetPath(volume);
514 cherokee_buffer_add_va (&xml, VIRT_DISK_XML, file, device);
515 free(file);
517 virStorageVolFree(volume);
518 ret = ret_ok;
523 else if (strcmp(temp, "interface") == 0) {
524 void *mac, *ip;
525 if ((ret = cherokee_avl_get_ptr (conn->arguments, "mac", &mac)) == ret_ok && (ret = cherokee_avl_get_ptr (conn->arguments, "ip", &ip)) == ret_ok) {
526 cherokee_buffer_add_va (&xml, VIRT_INTERFACE_XML, mac, ip);
527 } else {
528 char *mac = NULL;
529 char *ip = NULL;
530 cherokee_buffer_t domu = CHEROKEE_BUF_INIT;
531 cherokee_buffer_add_va (&domu, "%s_%s", hdl->user.buf, hdl->vm.buf);
532 if (getNewMac("dv28", domu.buf, &mac, &ip) == 0)
533 cherokee_buffer_add_va (&xml, VIRT_INTERFACE_XML, mac, ip);
534 cherokee_buffer_mrproper(&domu);
538 if (ret == ret_ok && (result = virDomainAttachDevice(dom, (const char *) xml.buf)) == 0) {
539 ret = ret_ok;
540 } else {
541 conn->error_code = http_internal_error;
542 return ret_error;
545 cherokee_buffer_add_long10(buf, result);
546 cherokee_buffer_mrproper(&xml);
547 } else {
548 TRACE("virt", "DeviceAttach_args; type was not specified");
549 conn->error_code = http_bad_request;
550 return ret_error;
553 break;
556 case domainAttachDevice: {
557 off_t postl;
558 int result;
559 cherokee_buffer_t post = CHEROKEE_BUF_INIT;
560 cherokee_post_get_len (&conn->post, &postl);
561 cherokee_post_walk_read (&conn->post, &post, (cuint_t) postl);
562 if ((result = virDomainAttachDevice(dom, (const char *) post.buf)) != 0)
563 conn->error_code = http_internal_error;
565 cherokee_buffer_mrproper(&post);
566 cherokee_buffer_add_long10(buf, result);
567 break;
571 case domainGetXMLDesc: {
572 char *xml = virDomainGetXMLDesc(dom, 0);
573 cherokee_buffer_add(buf, xml, strlen(xml));
574 free(xml);
575 break;
579 case domainDetachDevice: {
580 off_t postl;
581 int result;
582 ret_t ret;
583 cherokee_buffer_t post = CHEROKEE_BUF_INIT;
584 cherokee_post_get_len (&conn->post, &postl);
585 cherokee_post_walk_read (&conn->post, &post, (cuint_t) postl);
587 xmlDocPtr doc = xmlParseMemory((const char *) post.buf, post.len);
588 if (doc == NULL) {
589 TRACE("virt", "DeviceAttach; XML document unparceble");
590 conn->error_code = http_bad_request;
591 ret = ret_error;
592 } else
593 ret = ret_ok;
595 if (ret == ret_ok) {
596 if ((result = virDomainDetachDevice(dom, (const char *) post.buf)) != 0) {
597 conn->error_code = http_internal_error;
598 /* TODO: betere afhandeling */
600 xmlXPathContextPtr context = xmlXPathNewContext(doc);
601 if (context != NULL) {
602 xmlXPathObjectPtr obj = xmlXPathEval("string(//interface/mac/@address)", context);
603 xmlXPathFreeContext(context);
604 if ((obj != NULL) && (obj->type == XPATH_STRING) &&
605 (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
606 removeOldMac("dv28", (char *) obj->stringval);
608 xmlXPathFreeObject(obj);
611 xmlFreeDoc(doc);
612 xmlCleanupParser();
615 cherokee_buffer_mrproper(&post);
616 cherokee_buffer_add_long10(buf, result);
617 break;
620 case domainGetID: {
621 cherokee_buffer_add_ulong10(buf, virDomainGetID(dom));
622 break;
624 case domainGetMaxMemory: {
625 cherokee_buffer_add_ulong10(buf, virDomainGetMaxMemory (dom));
626 break;
628 case domainGetMaxVcpus: {
629 cherokee_buffer_add_long10(buf, virDomainGetMaxVcpus (dom));
630 break;
632 case domainGetName: {
633 const char *name = virDomainGetName (dom);
634 cherokee_buffer_add(buf, name, strlen(name));
635 break;
637 case domainGetUUID: {
638 unsigned char uuid[VIR_UUID_BUFLEN];
639 if (virDomainGetUUID(dom, uuid) == 0) {
640 cherokee_buffer_add_str(buf, uuid);
641 } else {
642 conn->error_code = http_internal_error;
643 return ret_error;
645 break;
647 case domainGetUUIDString: {
648 unsigned char uuid[VIR_UUID_STRING_BUFLEN];
649 if (virDomainGetUUIDString(dom, uuid) == 0) {
650 cherokee_buffer_add_str(buf, uuid);
651 } else {
652 conn->error_code = http_internal_error;
653 return ret_error;
655 break;
658 case domainCreate: {
659 cherokee_buffer_add_long10(buf, virDomainCreate (dom));
660 break;
663 case domainDestroy: {
664 cherokee_buffer_add_long10(buf, virDomainDestroy (dom));
665 break;
668 case domainReboot: {
669 cherokee_buffer_add_long10(buf, virDomainReboot (dom, 0));
670 break;
673 case domainShutdown: {
674 cherokee_buffer_add_long10(buf, virDomainShutdown (dom));
675 break;
679 case domainGetOSType: {
680 char *ostype = virDomainGetOSType(dom);
681 cherokee_buffer_add(buf, ostype, strlen(ostype));
682 free(ostype);
683 break;
690 if (hdl->action == domainUndefine) {
691 /* Remove VM data from filesystem */
692 cherokee_buffer_t path = CHEROKEE_BUF_INIT;
693 cherokee_buffer_add_va (&path, "/mnt/netapp/users/%s/%s/index.xml", hdl->user.buf, hdl->vm.buf);
694 unlink(path.buf); /* TODO: instead of delet replace */
695 cherokee_buffer_mrproper(&path);
696 } else {
697 save_xml(hdl, dom, NULL);
700 return ret_ok;
703 static virStoragePoolPtr
704 virt_get_pool_by_args(cherokee_handler_virt_t *hdl, virConnectPtr virConn) {
705 cherokee_connection_t *conn = HANDLER_CONN(hdl);
706 virStoragePoolPtr pool;
707 void *temp;
708 ret_t ret;
710 ret = cherokee_avl_get_ptr (conn->arguments, "pool", &temp);
711 if (unlikely(ret < ret_ok)) {
712 TRACE("virt", "virStoragePoolPtr; Pool argument not specified");
713 conn->error_code = http_bad_request;
714 return NULL;
717 pool = virStoragePoolLookupByName(virConn, temp);
719 return pool;
722 static virStorageVolPtr
723 virt_get_vol_by_args(cherokee_handler_virt_t *hdl, virConnectPtr virConn, unsigned short int prefix) {
724 cherokee_connection_t *conn = HANDLER_CONN(hdl);
725 virStoragePoolPtr pool;
726 virStorageVolPtr volume;
727 void *temp;
728 ret_t ret;
730 pool = virt_get_pool_by_args(hdl, virConn);
732 if (pool == NULL) {
733 conn->error_code = http_not_found;
734 return NULL;
737 virStoragePoolRefresh(pool, 0); /* TODO: might be better to do it outside */
739 ret = cherokee_avl_get_ptr (conn->arguments, "volume", &temp);
740 if (unlikely(ret < ret_ok)) {
741 TRACE("virt", "virStorageVolPtr; Volume argument not specified");
742 conn->error_code = http_bad_request;
743 return NULL;
746 if (prefix == 1) {
747 cherokee_buffer_t fullvol = CHEROKEE_BUF_INIT;
748 cherokee_buffer_add_va (&fullvol, "%s_%s", hdl->user.buf, temp);
749 volume = virStorageVolLookupByName(pool, fullvol.buf);
750 cherokee_buffer_mrproper(&fullvol);
751 } else {
752 volume = virStorageVolLookupByName(pool, temp);
755 if (volume == NULL)
756 conn->error_code = http_not_found;
758 virStoragePoolFree(pool);
760 return volume;
763 /* This function is the home for all functions that need a working
764 * pool/volume combination */
765 static ret_t
766 virt_pool_vol(cherokee_handler_virt_t *hdl, virConnectPtr virConn) {
767 cherokee_buffer_t *buf = &HDL_AVAHI(hdl)->buffer;
768 cherokee_connection_t *conn = HANDLER_CONN(hdl);
769 virStorageVolPtr volume;
770 ret_t ret = ret_ok;
772 /* We only allow clone to run 'unsafe', others get prefixed */
773 volume = virt_get_vol_by_args(hdl, virConn, (hdl->action != storageVolCloneXML_args));
775 /* If the volume doesn't exist, no point to continue */
776 if (volume == NULL)
777 return ret_error;
779 switch (hdl->action) {
780 /* Sets the password of a specific volume, requires the password= option */
781 case storageVolSetPassword_args: {
782 void *temp;
783 ret = cherokee_avl_get_ptr (conn->arguments, "password", &temp);
784 if (unlikely(ret < ret_ok)) {
785 TRACE("virt", "storageVolSetPassword_args; password argument not specified");
786 conn->error_code = http_bad_request;
787 goto virt_pool_vol_cleanup;
788 } else {
789 cherokee_buffer_t cmd_passwd = CHEROKEE_BUF_INIT;
790 cherokee_buffer_add_va (&cmd_passwd, "/usr/sbin/passwdchanger.sh %s %s\n", virStorageVolGetKey(volume), temp);
791 cherokee_buffer_add_long10(buf, system(cmd_passwd.buf));
792 cherokee_buffer_mrproper(&cmd_passwd);
794 break;
797 /* Removes a volume */
798 case storageVolDelete_args: {
799 cherokee_buffer_add_long10(buf, virStorageVolDelete(volume, 0));
800 break;
803 /* Gives a description of a storage volume in XML */
804 case storageVolGetXMLDesc_args: {
805 char *xml = virStorageVolGetXMLDesc(volume, 0);
806 cherokee_buffer_add(buf, xml, strlen(xml));
807 free(xml);
808 break;
811 /* Clones a volume, insecure method! requires a new name= */
812 case storageVolCloneXML_args: {
813 void *name;
814 cherokee_buffer_t busy = CHEROKEE_BUF_INIT;
816 ret = cherokee_avl_get_ptr (conn->arguments, "name", &name);
817 if (unlikely(ret < ret_ok)) {
818 TRACE("virt", "storageVolCloneXML_args; name argument not specified");
819 conn->error_code = http_bad_request;
820 goto virt_pool_vol_cleanup;
823 cherokee_buffer_add_va (&busy, "/mnt/images/queue/%s_%s.queued", hdl->user.buf, name);
825 if (unlikely(symlink(virStorageVolGetKey(volume), busy.buf) == 1)) {
826 conn->error_code = http_internal_error;
827 goto virt_pool_vol_cleanup;
830 cherokee_buffer_mrproper(&busy);
831 cherokee_buffer_add_str(buf, "QUEUED");
833 break;
837 virt_pool_vol_cleanup:
838 /* And in the end we need to free the volume we have used */
839 virStorageVolFree(volume);
841 return ret;
844 static ret_t
845 virt_virt_new(cherokee_handler_virt_t *hdl, virConnectPtr virConn) {
846 cherokee_buffer_t *buf = &HDL_AVAHI(hdl)->buffer;
847 cherokee_connection_t *conn = HANDLER_CONN(hdl);
848 cherokee_buffer_t xml = CHEROKEE_BUF_INIT;
849 virStoragePoolPtr pool = NULL;
850 ret_t ret = ret_ok;
852 switch (hdl->action) {
853 case storageVolCreateXML_args: {
854 void *temp, *type, *name, *unit;
855 unsigned long int capacity, allocation;
857 ret = cherokee_avl_get_ptr (conn->arguments, "pool", &temp);
858 if (unlikely(ret < ret_ok)) {
859 TRACE("virt", "storageVolCreateXML_args; pool argument not specified");
860 conn->error_code = http_bad_request;
861 goto virt_virt_new_cleanup;
864 pool = virStoragePoolLookupByName(virConn, temp);
866 if (pool == NULL) {
867 conn->error_code = http_not_found;
868 goto virt_virt_new_cleanup;
871 ret = cherokee_avl_get_ptr (conn->arguments, "name", &name);
872 if (unlikely(ret < ret_ok)) {
873 TRACE("virt", "storageVolCreateXML_args; name argument not specified");
874 conn->error_code = http_bad_request;
875 goto virt_virt_new_cleanup;
878 ret = cherokee_avl_get_ptr (conn->arguments, "type", &type);
879 if (unlikely(ret < ret_ok)) {
880 TRACE("virt", "storageVolCreateXML_args; type argument not specified");
881 conn->error_code = http_bad_request;
882 goto virt_virt_new_cleanup;
885 ret = cherokee_avl_get_ptr (conn->arguments, "unit", &unit);
886 if (unlikely(ret < ret_ok)) {
887 TRACE("virt", "storageVolCreateXML_args; unit argument not specified");
888 conn->error_code = http_bad_request;
889 goto virt_virt_new_cleanup;
892 ret = cherokee_avl_get_ptr (conn->arguments, "allocation", &temp);
893 if (unlikely(ret < ret_ok)) {
894 TRACE("virt", "storageVolCreateXML_args; allocation argument not specified");
895 conn->error_code = http_bad_request;
896 goto virt_virt_new_cleanup;
899 allocation = strtoul(temp, NULL, 10);
900 if (errno == ERANGE) {
901 TRACE("virt", "storageVolCreateXML_args; allocation is not a number");
902 conn->error_code = http_bad_request;
903 ret = ret_error;
904 goto virt_virt_new_cleanup;
907 ret = cherokee_avl_get_ptr (conn->arguments, "capacity", &temp);
908 if (unlikely(ret < ret_ok)) {
909 TRACE("virt", "storageVolCreateXML_args; capacity argument not specified");
910 conn->error_code = http_bad_request;
911 goto virt_virt_new_cleanup;
914 capacity = strtoul(temp, NULL, 10);
915 if (errno == ERANGE || capacity == 0) {
916 TRACE("virt", "storageVolCreateXML_args; capacity is not a number");
917 conn->error_code = http_bad_request;
918 ret = ret_error;
919 goto virt_virt_new_cleanup;
922 cherokee_buffer_add_va (&xml, VIRT_STORAGE_XML, type, hdl->user.buf, name, allocation, unit, capacity, hdl->user.buf, name, hdl->user.buf, name);
923 break;
926 case domainDefineXML_args: {
927 ret_t ret;
928 unsigned int i;
929 unsigned long vcpu = 0, interface = 0, memory = 0;
931 void *temp = NULL;
933 ret = cherokee_avl_get_ptr (conn->arguments, "vcpu", &temp);
934 if (ret == ret_ok)
935 vcpu = strtoul(temp, (char **) NULL, 10);
937 if (ret != ret_ok || errno == ERANGE || vcpu == 0) {
938 conn->error_code = http_internal_error;
939 goto virt_virt_new_cleanup;
943 ret = cherokee_avl_get_ptr (conn->arguments, "memory", &temp);
944 if (ret == ret_ok)
945 memory = strtoul(temp, (char **) NULL, 10);
947 if (ret != ret_ok || errno == ERANGE || memory == 0) {
948 conn->error_code = http_internal_error;
949 goto virt_virt_new_cleanup;
953 ret = cherokee_avl_get_ptr (conn->arguments, "interface", &temp);
954 if (ret == ret_ok)
955 interface = strtoul(temp, (char **) NULL, 10);
957 if (ret != ret_ok || errno == ERANGE) {
958 conn->error_code = http_internal_error;
959 goto virt_virt_new_cleanup;
962 cherokee_buffer_t cmdline_extra = CHEROKEE_BUF_INIT;
963 cherokee_buffer_t xml_interfaces = CHEROKEE_BUF_INIT;
964 cherokee_buffer_t domu = CHEROKEE_BUF_INIT;
965 cherokee_buffer_add_va (&domu, "%s_%s", hdl->user.buf, hdl->vm.buf);
967 for (i = 0; i < interface; i++) {
968 char *mac = NULL;
969 char *ip = NULL;
970 if (getNewMac("dv28", domu.buf, &mac, &ip) == 0) {
971 cherokee_buffer_add_va (&xml_interfaces, VIRT_INTERFACE_XML, mac, ip);
972 if (i == 0) {
973 /* TODO: terrible hack */
974 char gateway[16];
975 char *temp;
976 strcpy(gateway, ip);
977 temp = strchr(gateway, '.');
978 temp = strchr(++temp, '.');
979 temp = strchr(++temp, '.');
980 strcpy(++temp, "254");
981 cherokee_buffer_add_va (&cmdline_extra, VIRT_DOMAIN_CMD_IP, ip, gateway);
986 cherokee_buffer_mrproper(&domu);
988 cherokee_buffer_add_va (&xml, VIRT_DOMAIN_XML,
989 hdl->user.buf, hdl->vm.buf, cmdline_extra.buf, memory, vcpu, xml_interfaces.buf);
991 cherokee_buffer_mrproper(&xml_interfaces);
992 cherokee_buffer_mrproper(&cmdline_extra);
993 break;
996 case storageVolCreateXML:
997 case domainDefineXML: {
998 off_t postl;
999 cherokee_post_get_len (&conn->post, &postl);
1000 cherokee_post_walk_read (&conn->post, &xml, (cuint_t) postl);
1001 break;
1005 switch (hdl->action) {
1006 case domainDefineXML_args:
1007 case domainDefineXML: {
1008 virDomainPtr result = virDomainDefineXML(virConn, (const char *) xml.buf);
1010 if (result == NULL) {
1011 /* TODO: vrij maken eventuele uitgegeven macs! */
1012 conn->error_code = http_internal_error;
1013 goto virt_virt_new_cleanup;
1016 save_xml(hdl, result, buf);
1018 virDomainFree(result);
1020 break;
1023 case storageVolCreateXML_args:
1024 case storageVolCreateXML: {
1025 virStorageVolPtr vol = virStorageVolCreateXML(pool, xml.buf, 0);
1027 if (vol == NULL) {
1028 cherokee_buffer_add_long10(buf, -1);
1029 goto virt_virt_new_cleanup;
1032 virStorageVolFree(vol);
1034 cherokee_buffer_add_long10(buf, 0);
1035 break;
1039 virt_virt_new_cleanup:
1040 cherokee_buffer_mrproper(&xml);
1042 if (pool)
1043 virStoragePoolFree(pool);
1045 return ret;
1049 static ret_t
1050 virt_virt_do(cherokee_handler_virt_t *hdl, cherokee_buffer_t *domu, cherokee_buffer_t *uri)
1052 cherokee_connection_t *conn = HANDLER_CONN(hdl);
1054 ret_t ret = ret_error;
1055 virConnectPtr virConn = NULL;
1058 if (HDL_VIRT_PROPS(hdl)->read_only == FALSE)
1059 virConn = virConnectOpen (uri->buf);
1061 if (!virConn && !(virConn = virConnectOpenReadOnly (uri->buf))) {
1062 conn->error_code = http_service_unavailable;
1063 return ret_error;
1066 switch (hdl->action) {
1067 case storageVolDelete_args:
1068 case storageVolSetPassword_args:
1069 case storageVolGetXMLDesc_args:
1070 case storageVolCloneXML_args:
1071 ret = virt_pool_vol(hdl, virConn);
1072 break;
1074 case storageVolCreateXML_args:
1075 case storageVolCreateXML:
1076 case domainDefineXML_args:
1077 case domainDefineXML:
1078 ret = virt_virt_new(hdl, virConn);
1079 break;
1081 default: {
1082 virDomainPtr dom;
1083 if ((dom = virDomainLookupByName(virConn, domu->buf)) == NULL) {
1084 conn->error_code = http_not_found;
1085 } else {
1086 ret = virt_virt_function(hdl, dom, virConn);
1087 virDomainFree(dom);
1092 virConnectClose(virConn);
1093 return ret;
1096 static ret_t
1097 virt_while (cherokee_buffer_t *key, void *value, void *param) {
1098 cherokee_handler_virt_t * hdl = param;
1099 // cherokee_buffer_t uri = CHEROKEE_BUF_INIT;
1100 // cherokee_buffer_add_va (&uri, "xen://%s/", ((cherokee_buffer_t *) value)->buf);
1101 // virt_virt_do((cherokee_handler_virt_t *) param, key, &uri);
1102 // cherokee_buffer_mrproper(&uri);
1104 cherokee_buffer_add_va (&hdl->buffer, "<domain><name>%s</name></domain>", key->buf);
1106 return ret_ok;
1109 static ret_t
1110 virt_while_user (cherokee_buffer_t *key, void *value, void *param) {
1111 cherokee_handler_virt_t *hdl = param;
1112 if (key->len > hdl->user.len && key->buf[hdl->user.len] == '_' && strncmp(key->buf, hdl->user.buf, hdl->user.len) == 0)
1113 return virt_while (key, value, param);
1115 return ret_ok;
1118 static ret_t
1119 virt_build_page (cherokee_handler_virt_t *hdl)
1121 ret_t ret;
1122 cherokee_connection_t *conn = HANDLER_CONN(hdl);
1123 cherokee_buffer_t uri = CHEROKEE_BUF_INIT;
1124 cherokee_buffer_t domu = CHEROKEE_BUF_INIT;
1126 /* We use the webserver methods to parse the querystring */
1127 /* Maybe do something smart with ENUM, begin_args, end_args... */
1128 if ((hdl->action == domainDefineXML_args) ||
1129 (hdl->action == domainAttachDevice_args) ||
1130 (hdl->action == storageVolGetXMLDesc_args) ||
1131 (hdl->action == storageVolDelete_args) ||
1132 (hdl->action == storageVolSetPassword_args) ||
1133 (hdl->action == storageVolCloneXML_args) ||
1134 (hdl->action == storageVolCreateXML_args) ||
1135 (hdl->action == graphLoad_args) ||
1136 (hdl->action == graphInterface_args)) {
1137 ret = cherokee_connection_parse_args (conn);
1138 if (unlikely(ret < ret_ok)) {
1139 conn->error_code = http_internal_error;
1140 return ret_error;
1144 switch (hdl->action) {
1145 case graphInterface_args: {
1146 struct stat statbuf;
1147 cherokee_buffer_t path = CHEROKEE_BUF_INIT;
1148 void *interface;
1149 if ((ret = cherokee_avl_get_ptr (conn->arguments, "interface", &interface)) != ret_ok)
1150 interface = "eth0";
1152 cherokee_buffer_add_va (&path, "/mnt/netapp/users/%s/%s/interface_%s.rrd", hdl->user.buf, hdl->vm.buf, interface);
1153 if (stat(path.buf, &statbuf) != 0) {
1154 conn->error_code = http_not_found;
1155 ret = ret_error;
1156 } else {
1157 void *width, *height, *start, *end;
1158 if ((ret = cherokee_avl_get_ptr (conn->arguments, "width", &width)) != ret_ok)
1159 width = "600";
1161 if ((ret = cherokee_avl_get_ptr (conn->arguments, "height", &height)) != ret_ok)
1162 height = "200";
1164 if ((ret = cherokee_avl_get_ptr (conn->arguments, "start", &start)) != ret_ok)
1165 start = "now-1h";
1167 if ((ret = cherokee_avl_get_ptr (conn->arguments, "end", &end)) != ret_ok)
1168 end = "now";
1170 cherokee_buffer_t def1 = CHEROKEE_BUF_INIT;
1171 cherokee_buffer_t def2 = CHEROKEE_BUF_INIT;
1172 cherokee_buffer_add_va (&def1, "DEF:rxbytes=%s:rxbytes:AVERAGE:step=30", path.buf);
1173 cherokee_buffer_add_va (&def2, "DEF:txbytes=%s:txbytes:AVERAGE:step=30", path.buf);
1174 char **calcpr = NULL;
1175 int xsize, ysize;
1176 double ymin, ymax;
1177 char *filename = mktemp(strdup("handler_virt_XXXXXX"));
1178 char *r_graph[] = { "rrdgraph", filename,
1179 "-a", "PNG",
1180 "-w", width,
1181 "-h", height,
1182 "--start", start,
1183 "--end", end,
1184 "--title", interface,
1185 "--lower-limit", "0", "--alt-autoscale-max", "--vertical-label", "bits per second",
1186 def1.buf,
1187 def2.buf,
1188 "CDEF:txbits=txbytes,8,*",
1189 "CDEF:rxbits=rxbytes,8,*",
1190 "AREA:rxbits#00EE00:rxbits",
1191 "LINE:txbits#0000EE:txbits" };
1193 rrd_graph(25, r_graph, &calcpr, &xsize, &ysize, NULL, &ymin, &ymax);
1194 if ((ret = cherokee_buffer_read_file(&hdl->buffer, filename)) == ret_error) {
1195 hdl->action = http_internal_error;
1198 unlink(filename);
1199 free(filename);
1201 cherokee_buffer_mrproper(&def1);
1202 cherokee_buffer_mrproper(&def2);
1204 cherokee_buffer_mrproper(&path);
1205 goto virt_build_page_cleanup;
1210 case graphLoad_args: {
1211 struct stat statbuf;
1212 cherokee_buffer_t path = CHEROKEE_BUF_INIT;
1213 cherokee_buffer_add_va (&path, "/mnt/netapp/users/%s/%s/cpuTime.rrd", hdl->user.buf, hdl->vm.buf);
1214 if (stat(path.buf, &statbuf) != 0) {
1215 conn->error_code = http_not_found;
1216 ret = ret_error;
1217 } else {
1218 void *width, *height, *start, *end;
1219 if ((ret = cherokee_avl_get_ptr (conn->arguments, "width", &width)) != ret_ok)
1220 width = "600";
1222 if ((ret = cherokee_avl_get_ptr (conn->arguments, "height", &height)) != ret_ok)
1223 height = "200";
1225 if ((ret = cherokee_avl_get_ptr (conn->arguments, "start", &start)) != ret_ok)
1226 start = "now-1h";
1228 if ((ret = cherokee_avl_get_ptr (conn->arguments, "end", &end)) != ret_ok)
1229 end = "now";
1231 /* TODO: wat error checking? */
1233 cherokee_buffer_t def = CHEROKEE_BUF_INIT;
1234 cherokee_buffer_add_va (&def, "DEF:cputime=%s:cpuTime:AVERAGE:step=30", path.buf);
1235 char **calcpr = NULL;
1236 int xsize, ysize;
1237 double ymin, ymax;
1238 char *filename = mktemp(strdup("handler_virt_XXXXXX"));
1239 char *r_graph[] = { "rrdgraph",
1240 filename,
1241 "-a", "PNG",
1242 "-w", width,
1243 "-h", height,
1244 "--start", start,
1245 "--end", end,
1246 "--title", hdl->vm.buf,
1247 "--lower-limit", "0", "--alt-autoscale-max", "--vertical-label", "(used / total) time",
1248 def.buf,
1249 "CDEF:cpuload=cputime,1000000000,/",
1250 "LINE:cpuload#EE0000:cpuLoad" };
1252 rrd_graph(22, r_graph, &calcpr, &xsize, &ysize, NULL, &ymin, &ymax);
1253 if ((ret = cherokee_buffer_read_file(&hdl->buffer, filename)) == ret_error) {
1254 hdl->action = http_internal_error;
1257 unlink(filename);
1258 free(filename);
1260 cherokee_buffer_mrproper(&def);
1262 cherokee_buffer_mrproper(&path);
1263 goto virt_build_page_cleanup;
1267 if (hdl->action > xml && HDL_VIRT_PROPS(hdl)->xsl.len > 0)
1268 cherokee_buffer_add_va (&hdl->buffer, "<?xml version=\"1.0\"?>\n<?xml-stylesheet type=\"text/xsl\" href=\"%s\"?>\n", HDL_VIRT_PROPS(hdl)->xsl.buf);
1271 /* First, block the event loop */
1272 avahi_threaded_poll_lock(HDL_AVAHI_PROPS(hdl)->threaded_poll);
1273 switch (hdl->action) {
1274 case showall:
1275 cherokee_buffer_add_str (&hdl->buffer, "<domains>");
1276 cherokee_avl_while(&HDL_AVAHI_PROPS(hdl)->entries, virt_while, hdl, NULL, NULL);
1277 cherokee_buffer_add_str (&hdl->buffer, "</domains>");
1278 ret = ret_ok;
1279 break;
1281 case showuservms: {
1282 cherokee_buffer_add_str (&hdl->buffer, "<domains>");
1283 cherokee_avl_while(&HDL_AVAHI_PROPS(hdl)->entries, virt_while_user, hdl, NULL, NULL);
1284 cherokee_buffer_add_str (&hdl->buffer, "</domains>");
1285 ret = ret_ok;
1286 break;
1289 default: {
1290 cherokee_buffer_t *hostname = NULL;
1291 cherokee_buffer_add_va (&domu, "%s_%s", hdl->user.buf, hdl->vm.buf);
1292 ret = cherokee_avl_get_ptr(&HDL_AVAHI_PROPS(hdl)->entries, domu.buf, (void **) &hostname);
1294 if (ret == ret_not_found) {
1295 virDomainPtr virDom;
1296 virConnectPtr virConn;
1297 cherokee_buffer_add_va (&uri, "xen://%s/", HDL_VIRT_PROPS(hdl)->virt); // TODO: change!
1299 /* If we have the read only parameter, we will set up a connection to the
1300 * Hypervisor here. */
1301 if (HDL_VIRT_PROPS(hdl)->read_only == FALSE)
1302 virConn = virConnectOpen (uri.buf);
1304 /* We should already have a connection (read only) or build a new connection
1305 * if this doesn't work, we can safely assume our services is fubar */
1306 if (!virConn && !(virConn = virConnectOpenReadOnly (uri.buf))) {
1307 conn->error_code = http_service_unavailable;
1308 return ret_error;
1311 /* We lookup if there is a domain somewhere with this name */
1312 if ((virDom = virDomainLookupByName(virConn, domu.buf)) == NULL) {
1313 /* If the domain is not found on the network the only possible
1314 * command that is possible would be to Define it */
1315 if (hdl->action == domainDefineXML_args || hdl->action == domainDefineXML) {
1316 ret = ret_ok;
1317 } else {
1318 /* Otherwise we don't have anything to do and we should
1319 * return an error */
1320 hdl->action = nothing;
1321 conn->error_code = http_not_found;
1322 ret = ret_error;
1324 } else {
1325 /* We don't want te recreate things that already found on the network
1326 * first undefine them! */
1327 if (hdl->action == domainDefineXML_args || hdl->action == domainDefineXML) {
1328 TRACE("virt", "domainDefineXML_args/domainDefineXML; domain already exists");
1329 hdl->action = nothing;
1330 conn->error_code = http_bad_request;
1331 ret = ret_error;
1332 } else {
1333 /* Everything is ok, because nothing is found. */
1334 ret = ret_ok;
1337 /* Domain wasn't NULL, so we should free it here */
1338 virDomainFree(virDom);
1340 virConnectClose (virConn);
1341 } else if (ret == ret_ok) {
1342 cherokee_buffer_add_va (&uri, "xen://%s/", hostname->buf);
1343 printf("%s\n", uri.buf);
1344 } else {
1345 hdl->action = http_internal_error;
1346 hdl->action = nothing;
1347 ret = ret_error;
1352 /* Finally, unblock the event loop */
1353 avahi_threaded_poll_unlock(HDL_AVAHI_PROPS(hdl)->threaded_poll);
1355 if (ret == ret_ok && hdl->action != showall && hdl->action != showuservms) {
1356 ret = virt_virt_do(hdl, &domu, &uri);
1359 virt_build_page_cleanup:
1360 cherokee_buffer_mrproper(&domu);
1361 cherokee_buffer_mrproper(&uri);
1363 return ret;
1367 ret_t
1368 cherokee_handler_virt_new (cherokee_handler_t **hdl, cherokee_connection_t *cnt, cherokee_module_props_t *props)
1370 ret_t ret;
1371 CHEROKEE_NEW_STRUCT (n, handler_virt);
1373 /* Init the base class
1376 cherokee_handler_init_base(HANDLER(n), cnt, HANDLER_PROPS(props), PLUGIN_INFO_HANDLER_PTR(virt));
1378 MODULE(n)->init = (handler_func_init_t) cherokee_handler_virt_init;
1379 MODULE(n)->free = (module_func_free_t) cherokee_handler_virt_free;
1380 HANDLER(n)->step = (handler_func_step_t) cherokee_handler_virt_step;
1381 HANDLER(n)->add_headers = (handler_func_add_headers_t) cherokee_handler_virt_add_headers;
1383 HANDLER(n)->support = hsupport_length | hsupport_range;
1385 ret = cherokee_buffer_init (&n->buffer);
1386 if (unlikely(ret != ret_ok))
1387 return ret;
1389 ret = cherokee_buffer_ensure_size (&n->buffer, 4*1024);
1390 if (unlikely(ret != ret_ok))
1391 return ret;
1393 *hdl = HANDLER(n);
1395 return ret_ok;