blabla
[handlervirt.git] / handler_virt.c
blobba3113b39aa29a84b99b1fde4f551894c373169c
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='qcow' />" \
41 " <source file='%s'/>" \
42 " <target dev='%s' bus='xen'/>" \
43 " </disk>"
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</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>
86 /* Plug-in initialization
88 * In this function you can use any of these:
89 * http_delete | http_get | http_post | http_put
91 * For a full list: cherokee_http_method_t
93 * It is what your handler to be implements.
96 PLUGIN_INFO_HANDLER_EASIEST_INIT (virt, http_get | http_post);
99 /* Methods implementation
101 static ret_t
102 props_free (cherokee_handler_virt_props_t *props)
105 cherokee_buffer_mrproper(&props->xsl);
106 cherokee_buffer_mrproper(&props->virt);
107 return cherokee_module_props_free_base (MODULE_PROPS(props));
111 ret_t
112 cherokee_handler_virt_configure (cherokee_config_node_t *conf, cherokee_server_t *srv, cherokee_module_props_t **_props)
114 cherokee_list_t *i;
115 cherokee_handler_virt_props_t *props;
117 /* Instance a new property object
120 if (*_props == NULL) {
121 CHEROKEE_NEW_STRUCT (n, handler_virt_props);
123 cherokee_handler_avahi_props_init_base (PROP_AVAHI(n), MODULE_PROPS_FREE(props_free));
125 /* Look at handler_virt.h
126 * This is an virt of configuration.
128 n->authenticate = true; /* by default we are secure! */
129 n->read_only = true; /* by default we are secure! */
130 cherokee_buffer_init (&n->xsl); /* we support a custom header */
131 cherokee_buffer_init (&n->virt); /* your first xenserver */
133 *_props = MODULE_PROPS(n);
136 props = PROP_VIRT(*_props);
138 cherokee_config_node_foreach (i, conf) {
139 cherokee_config_node_t *subconf = CONFIG_NODE(i);
141 if (equal_buf_str (&subconf->key, "authenticate")) {
142 props->authenticate = atoi(subconf->val.buf);
144 else if (equal_buf_str (&subconf->key, "read_only")) {
145 props->read_only = atoi(subconf->val.buf);
147 else if (equal_buf_str (&subconf->key, "xsl")) {
148 cherokee_buffer_add_buffer (&props->xsl, &subconf->val);
150 else if (equal_buf_str (&subconf->key, "virt")) {
151 cherokee_buffer_add_buffer (&props->virt, &subconf->val);
156 /* Init base class
159 return cherokee_handler_avahi_configure (conf, srv, _props);
163 ret_t
164 cherokee_handler_virt_init (cherokee_handler_virt_t *hdl)
166 int isroot = false;
167 int len;
168 char *this, *next;
170 cherokee_connection_t *conn = HANDLER_CONN(hdl);
171 cherokee_buffer_init(&hdl->user);
172 cherokee_buffer_init(&hdl->vm);
174 hdl->action = nothing;
176 cherokee_buffer_add (&conn->pathinfo,
177 conn->request.buf + conn->web_directory.len,
178 conn->request.len - conn->web_directory.len);
180 this = conn->pathinfo.buf + 1;
181 next = strchr(this, '/');
184 if ((!next && (this && (len = strlen(this)) == 0)) || (next && ((len = next - this) == 0)) )
185 hdl->action = showall;
186 else {
187 cherokee_buffer_add (&hdl->user, this, len);
190 if (HDL_VIRT_PROPS(hdl)->authenticate) {
191 if (!conn->validator ||
192 (conn->validator &&
193 (!cherokee_buffer_cmp_buf(&conn->validator->user, &hdl->user) &&
194 !(isroot = cherokee_buffer_cmp (&conn->validator->user, "root", 4))))) {
195 hdl->action = nothing; /* just in case */
196 conn->error_code = http_unauthorized;
197 return ret_error;
199 } else {
200 isroot = true;
203 if (hdl->action == showall) {
204 if (!isroot) {
205 hdl->action = nothing;
206 conn->error_code = http_unauthorized;
207 return ret_error;
208 } else {
209 return virt_build_page(hdl);
214 if (!next) {
215 hdl->action = showuservms;
216 return virt_build_page(hdl);
217 } else {
218 this = next + 1;
219 next = strchr(this, '/');
221 if (!next && (this && (len = strlen(this)) == 0) || (next && ((len = next - this) == 0)) ) {
222 hdl->action = showuservms;
223 return virt_build_page(hdl);
227 cherokee_buffer_add (&hdl->vm, this, len);
229 if (!next) {
230 hdl->action = domainGetXMLDesc;
231 return virt_build_page(hdl);
232 } else {
233 this = next + 1;
234 next = strchr(this, '/');
236 if (!next && (this && (len = strlen(this)) == 0) || (next && ((len = next - this) == 0)) ) {
237 hdl->action = domainGetXMLDesc;
238 return virt_build_page(hdl);
242 hdl->action = not_implemented;
243 switch (conn->header.method) {
244 case http_get:
245 if (strncmp(this, "virDomain", 9) == 0) {
246 if (strncmp(this+9, "Get", 3) == 0) {
247 if (strcmp(this+12, "ID") == 0) hdl->action = domainGetID;
248 else if (strcmp(this+12, "Name") == 0) hdl->action = domainGetName;
249 else if (strcmp(this+12, "MaxMemory") == 0) hdl->action = domainGetMaxMemory;
250 else if (strcmp(this+12, "MaxVcpus") == 0) hdl->action = domainGetMaxVcpus;
251 else if (strcmp(this+12, "OSType") == 0) hdl->action = domainGetOSType;
252 else if (strcmp(this+12, "UUID") == 0) hdl->action = domainGetUUID;
253 else if (strcmp(this+12, "UUIDString") == 0) hdl->action = domainGetUUIDString;
254 else if (strcmp(this+12, "XMLDesc") == 0) hdl->action = domainGetXMLDesc;
256 else if (strcmp(this+9, "Create") == 0) hdl->action = domainCreate;
257 else if (strcmp(this+9, "Destroy") == 0) hdl->action = domainDestroy;
258 else if (strcmp(this+9, "Reboot") == 0) hdl->action = domainReboot;
259 else if (strcmp(this+9, "Shutdown") == 0) hdl->action = domainShutdown;
261 else if (strcmp(this+9, "AttachDevice") == 0) hdl->action = domainAttachDevice_args;
263 else if (strcmp(this+9, "DefineXML") == 0) hdl->action = domainDefineXML_args;
264 else if (strcmp(this+9, "Undefine") == 0) hdl->action = domainUndefine;
266 else if (strncmp(this, "virStorage", 10) == 0) {
267 if (strncmp(this+10, "Vol", 3) == 0) {
268 if (strcmp(this+13, "CreateXML") == 0) hdl->action = storageVolCreateXML_args;
269 else if (strcmp(this+13, "CloneXML") == 0) hdl->action = storageVolCloneXML_args;
270 else if (strcmp(this+13, "GetXMLDesc") == 0) hdl->action = storageVolGetXMLDesc;
273 break;
275 case http_post: {
276 off_t postl;
277 cherokee_post_get_len (&conn->post, &postl);
279 if (postl <= 0 || postl >= (INT_MAX-1)) {
280 conn->error_code = http_bad_request;
281 return ret_error;
284 if (strncmp(this, "virDomain", 9) == 0) {
285 if (strcmp(this+9, "AttachDevice") == 0) hdl->action = domainAttachDevice;
286 else if (strcmp(this+9, "DetachDevice") == 0) hdl->action = domainDetachDevice;
287 else if (strcmp(this+9, "DefineXML") == 0) hdl->action = domainDefineXML;
289 else if (strncmp(this, "virStorage", 10) == 0) {
290 if (strncmp(this+10, "Vol", 3) == 0) {
291 if (strcmp(this+13, "CreateXML") == 0) hdl->action = storageVolCreateXML;
295 break;
298 default:
299 return ret_error;
302 if (hdl->action <= 0) {
303 conn->error_code = http_bad_request;
304 return ret_error;
308 return virt_build_page(hdl);
311 ret_t
312 cherokee_handler_virt_free (cherokee_handler_virt_t *hdl)
314 cherokee_buffer_mrproper (&hdl->buffer);
315 cherokee_buffer_mrproper (&hdl->user);
316 cherokee_buffer_mrproper (&hdl->vm);
318 return ret_ok;
321 ret_t
322 cherokee_handler_virt_step (cherokee_handler_virt_t *hdl, cherokee_buffer_t *buffer)
324 cherokee_buffer_add_buffer (buffer, &hdl->buffer);
325 return ret_eof_have_data;
328 ret_t
329 cherokee_handler_virt_add_headers (cherokee_handler_virt_t *hdl, cherokee_buffer_t *buffer)
331 cherokee_buffer_add_va (buffer, "Content-Length: %d"CRLF, hdl->buffer.len);
333 if (hdl->action > xml)
334 cherokee_buffer_add_str (buffer, "Content-Type: application/xml"CRLF);
335 else
336 cherokee_buffer_add_str (buffer, "Content-Type: text/plain"CRLF);
338 return ret_ok;
342 static ret_t
343 while_func_entries (cherokee_buffer_t *key, void *value, void *param) {
344 virConnectPtr conn = NULL;
345 cherokee_buffer_t uri = CHEROKEE_BUF_INIT;
346 cherokee_buffer_t *buf = (cherokee_buffer_t *)param;
348 cherokee_buffer_add_va (&uri, "xen://%s/", value);
350 if (HDL_VIRT_PROPS(hdl)->read_only == FALSE && !(conn = virConnectOpen (uri.buf))) {
351 if (!(conn = virConnectOpen (uri.buf))) {
352 return ret_error;
356 if (!conn && !(conn = virConnectOpenReadOnly (uri.buf))) {
357 return ret_error;
358 } else {
359 virDomainPtr dom;
360 if (!(dom = virDomainLookupByName(conn, (const char *) key->buf))) {
361 return ret_error;
362 } else {
363 char *xml = virDomainGetXMLDesc(dom, 0);
364 cherokee_buffer_add(buf, xml, strlen(xml));
366 virConnectClose(conn);
369 cherokee_buffer_mrproper(&uri);
371 return ret_ok;
374 static ret_t
375 virt_virt_function(cherokee_handler_virt_t *hdl, virDomainPtr dom) {
376 cherokee_connection_t *conn = HANDLER_CONN(hdl);
377 cherokee_buffer_t *buf = &HDL_AVAHI(hdl)->buffer;
379 switch (hdl->action) {
381 case domainUndefine: {
382 int result;
383 if ((result = virDomainUndefine(dom)) != 0) {
384 conn->error_code = http_internal_error;
387 cherokee_buffer_add_long10(buf, result);
388 break;
391 case domainAttachDevice_args: {
392 int result;
393 void *temp;
394 ret_t ret;
395 ret = cherokee_connection_parse_args (conn);
396 if (unlikely(ret < ret_ok))
397 return ret;
399 ret = cherokee_avl_get_ptr (conn->arguments, "type", &temp);
401 if (ret == ret_ok) {
402 cherokee_buffer_t xml = CHEROKEE_BUF_INIT;
404 if (strcmp(temp, "disk") == 0) {
405 void *file, *device;
407 if ((ret = cherokee_avl_get_ptr (conn->arguments, "file", &file)) == ret_ok && (ret = cherokee_avl_get_ptr (conn->arguments, "device", &device)) == ret_ok) {
408 cherokee_buffer_add_va (&xml, VIRT_DISK_XML, file, device);
409 } else {
410 ret = ret_error;
414 else if (strcmp(temp, "interface") == 0) {
415 void *mac, *ip;
416 if ((ret = cherokee_avl_get_ptr (conn->arguments, "mac", &mac)) == ret_ok && (ret = cherokee_avl_get_ptr (conn->arguments, "ip", &ip)) == ret_ok) {
417 cherokee_buffer_add_va (&xml, VIRT_INTERFACE_XML, mac, ip);
418 } else {
419 char *mac = NULL;
420 char *ip = NULL;
421 cherokee_buffer_t domu = CHEROKEE_BUF_INIT;
422 cherokee_buffer_add_va (&domu, "%s_%s", hdl->user.buf, hdl->vm.buf);
423 if (getNewMac("dv28", domu.buf, &mac, &ip) == 0)
424 cherokee_buffer_add_va (&xml, VIRT_INTERFACE_XML, mac, ip);
425 cherokee_buffer_mrproper(&domu);
431 if (ret == ret_ok && (result = virDomainAttachDevice(dom, (const char *) xml.buf)) == 0) {
432 ret = ret_ok;
433 } else {
434 conn->error_code = http_internal_error;
435 ret = ret_error;
438 cherokee_buffer_add_long10(buf, result);
439 cherokee_buffer_mrproper(&xml);
442 return ret;
445 case domainAttachDevice: {
446 off_t postl;
447 int result;
448 cherokee_buffer_t post = CHEROKEE_BUF_INIT;
449 cherokee_post_get_len (&conn->post, &postl);
450 cherokee_post_walk_read (&conn->post, &post, (cuint_t) postl);
451 if ((result = virDomainAttachDevice(dom, (const char *) post.buf)) != 0)
452 conn->error_code = http_internal_error;
454 cherokee_buffer_mrproper(&post);
455 cherokee_buffer_add_long10(buf, result);
456 break;
460 case domainGetXMLDesc: {
461 char *xml = virDomainGetXMLDesc(dom, 0);
462 cherokee_buffer_add(buf, xml, strlen(xml));
463 free(xml);
464 break;
468 case domainDetachDevice: {
469 off_t postl;
470 int result;
471 cherokee_buffer_t post = CHEROKEE_BUF_INIT;
472 cherokee_post_get_len (&conn->post, &postl);
473 cherokee_post_walk_read (&conn->post, &post, (cuint_t) postl);
474 if ((result = virDomainDetachDevice(dom, (const char *) post.buf)) != 0) {
475 conn->error_code = http_internal_error;
477 cherokee_buffer_mrproper(&post);
478 cherokee_buffer_add_long10(buf, result);
479 break;
482 case domainGetID: {
483 cherokee_buffer_add_ulong10(buf, virDomainGetID(dom));
484 break;
486 case domainGetMaxMemory: {
487 cherokee_buffer_add_ulong10(buf, virDomainGetMaxMemory (dom));
488 break;
490 case domainGetMaxVcpus: {
491 cherokee_buffer_add_long10(buf, virDomainGetMaxVcpus (dom));
492 break;
494 case domainGetName: {
495 const char *name = virDomainGetName (dom);
496 cherokee_buffer_add(buf, name, strlen(name));
497 break;
499 case domainGetUUID: {
500 unsigned char uuid[VIR_UUID_BUFLEN];
501 if (virDomainGetUUID(dom, uuid) == 0) {
502 cherokee_buffer_add_str(buf, uuid);
503 } else {
504 conn->error_code = http_internal_error;
505 return ret_error;
507 break;
509 case domainGetUUIDString: {
510 unsigned char uuid[VIR_UUID_STRING_BUFLEN];
511 if (virDomainGetUUIDString(dom, uuid) == 0) {
512 cherokee_buffer_add_str(buf, uuid);
513 } else {
514 conn->error_code = http_internal_error;
515 return ret_error;
517 break;
520 case domainCreate: {
521 cherokee_buffer_add_long10(buf, virDomainCreate (dom));
522 break;
525 case domainDestroy: {
526 cherokee_buffer_add_long10(buf, virDomainDestroy (dom));
527 break;
530 case domainReboot: {
531 cherokee_buffer_add_long10(buf, virDomainReboot (dom, 0));
532 break;
535 case domainShutdown: {
536 cherokee_buffer_add_long10(buf, virDomainShutdown (dom));
537 break;
541 case domainGetOSType: {
542 char *ostype = virDomainGetOSType(dom);
543 cherokee_buffer_add(buf, ostype, strlen(ostype));
544 free(ostype);
545 break;
551 return ret_ok;
554 static ret_t
555 virt_virt_new(cherokee_handler_virt_t *hdl, virConnectPtr virConn)
557 cherokee_buffer_t *buf = &HDL_AVAHI(hdl)->buffer;
558 cherokee_connection_t *conn = HANDLER_CONN(hdl);
559 cherokee_buffer_t xml = CHEROKEE_BUF_INIT;
560 virDomainPtr result;
561 virStoragePoolPtr pool;
562 virStorageVolPtr volume;
564 switch (hdl->action) {
565 case storageVolGetXMLDesc: {
566 cherokee_buffer_t fullvol = CHEROKEE_BUF_INIT;
567 void *temp;
568 ret_t ret;
569 ret = cherokee_connection_parse_args (conn);
571 if (unlikely(ret < ret_ok)) {
572 conn->error_code = http_internal_error;
573 return ret_error;
576 ret = cherokee_avl_get_ptr (conn->arguments, "pool", &temp);
577 if (unlikely(ret < ret_ok)) {
578 conn->error_code = http_bad_request;
579 return ret;
582 pool = virStoragePoolLookupByName(virConn, temp);
584 if (pool == NULL) {
585 conn->error_code = http_not_found;
586 return ret_error;
589 ret = cherokee_avl_get_ptr (conn->arguments, "volume", &temp);
590 if (unlikely(ret < ret_ok)) {
591 conn->error_code = http_bad_request;
592 return ret;
595 cherokee_buffer_add_va (&fullvol, "%s_%s", hdl->user.buf, temp);
596 printf("%s\n", fullvol.buf);
597 volume = virStorageVolLookupByName(pool, fullvol.buf);
599 cherokee_buffer_mrproper(&fullvol);
600 virStoragePoolFree(pool);
602 if (volume == NULL) {
603 conn->error_code = http_not_found;
604 return ret_error;
607 char *xml = virStorageVolGetXMLDesc(volume, 0);
608 virStorageVolFree(volume);
609 cherokee_buffer_add(buf, xml, strlen(xml));
610 free(xml);
612 break;
615 case storageVolCloneXML_args: {
616 void *temp, *name;
617 const char *source;
618 ret_t ret;
619 ret = cherokee_connection_parse_args (conn);
620 if (unlikely(ret < ret_ok)) {
621 conn->error_code = http_internal_error;
622 return ret_error;
625 ret = cherokee_avl_get_ptr (conn->arguments, "pool", &temp);
626 if (unlikely(ret < ret_ok)) {
627 conn->error_code = http_bad_request;
628 return ret;
631 pool = virStoragePoolLookupByName(virConn, temp);
633 if (pool == NULL) {
634 conn->error_code = http_not_found;
635 return ret_error;
638 ret = cherokee_avl_get_ptr (conn->arguments, "volume", &temp);
639 if (unlikely(ret < ret_ok)) {
640 conn->error_code = http_bad_request;
641 return ret;
644 volume = virStorageVolLookupByName(pool, temp);
646 if (volume == NULL) {
647 conn->error_code = http_not_found;
648 return ret_error;
651 source = virStorageVolGetKey(volume);
653 ret = cherokee_avl_get_ptr (conn->arguments, "name", &name);
654 if (unlikely(ret < ret_ok)) {
655 virStorageVolFree(volume);
656 virStoragePoolFree(pool);
657 conn->error_code = http_bad_request;
658 return ret;
661 ret = cherokee_avl_get_ptr (conn->arguments, "type", &temp);
662 if (unlikely(ret < ret_ok)) {
663 virStorageVolFree(volume);
664 virStoragePoolFree(pool);
665 conn->error_code = http_bad_request;
666 return ret;
670 enum { UNKNOWN, RAW, QCOW } clone = UNKNOWN;
672 if (strcmp("raw", temp) == 0)
673 clone = RAW;
674 else if (strcmp("qcow", temp) == 0)
675 clone = QCOW;
676 else {
677 virStorageVolFree(volume);
678 virStoragePoolFree(pool);
679 conn->error_code = http_bad_request;
680 return ret_error;
683 cherokee_buffer_t busy = CHEROKEE_BUF_INIT;
684 cherokee_buffer_add_va (&busy, "/mnt/images/queue/%s_%s.queued", hdl->user.buf, name);
686 if (unlikely(symlink(source, busy.buf) == 1)) {
687 virStorageVolFree(volume);
688 virStoragePoolFree(pool);
689 conn->error_code = http_internal_error;
690 return ret_error;
693 cherokee_buffer_mrproper(&busy);
694 cherokee_buffer_add_str(buf, "QUEUED");
696 break;
699 case storageVolCreateXML_args: {
700 void *temp, *type, *name, *unit;
701 unsigned long int capacity, allocation;
703 ret_t ret;
704 ret = cherokee_connection_parse_args (conn);
705 if (unlikely(ret < ret_ok)) {
706 conn->error_code = http_internal_error;
707 return ret;
710 ret = cherokee_avl_get_ptr (conn->arguments, "pool", &temp);
711 if (unlikely(ret < ret_ok)) {
712 conn->error_code = http_bad_request;
713 return ret;
716 pool = virStoragePoolLookupByName(virConn, temp);
718 if (pool == NULL) {
719 conn->error_code = http_not_found;
720 return ret_error;
723 ret = cherokee_avl_get_ptr (conn->arguments, "name", &name);
724 if (unlikely(ret < ret_ok)) {
725 conn->error_code = http_bad_request;
726 return ret;
729 ret = cherokee_avl_get_ptr (conn->arguments, "type", &type);
730 if (unlikely(ret < ret_ok)) {
731 conn->error_code = http_bad_request;
732 return ret;
735 ret = cherokee_avl_get_ptr (conn->arguments, "unit", &unit);
736 if (unlikely(ret < ret_ok)) {
737 conn->error_code = http_bad_request;
738 return ret;
741 ret = cherokee_avl_get_ptr (conn->arguments, "allocation", &temp);
742 if (unlikely(ret < ret_ok)) {
743 conn->error_code = http_bad_request;
744 return ret;
748 allocation = strtoul(temp, NULL, 10);
749 /* TODO: errno check */
751 ret = cherokee_avl_get_ptr (conn->arguments, "capacity", &temp);
752 if (unlikely(ret < ret_ok)) {
753 conn->error_code = http_bad_request;
754 return ret;
757 capacity = strtoul(temp, NULL, 10);
758 /* TODO: errno check */
760 cherokee_buffer_add_va (&xml, VIRT_STORAGE_XML, type, hdl->user.buf, name, allocation, unit, capacity, hdl->user.buf, name, hdl->user.buf, name);
761 printf("%s", xml.buf);
763 break;
766 case domainDefineXML_args: {
767 ret_t ret;
768 unsigned int i;
769 unsigned long vcpu = 0, interface = 0, memory = 0;
771 cherokee_buffer_t xml_interfaces = CHEROKEE_BUF_INIT;
772 void *temp = NULL;
774 ret = cherokee_connection_parse_args (conn);
775 if (unlikely(ret < ret_ok))
776 return ret;
778 ret = cherokee_avl_get_ptr (conn->arguments, "vcpu", &temp);
779 if (ret == ret_ok)
780 vcpu = strtoul(temp, (char **) NULL, 10);
782 if (ret != ret_ok || errno == ERANGE || vcpu == 0) {
783 conn->error_code = http_internal_error;
784 return ret_error;
788 ret = cherokee_avl_get_ptr (conn->arguments, "memory", &temp);
789 if (ret == ret_ok)
790 memory = strtoul(temp, (char **) NULL, 10);
792 if (ret != ret_ok || errno == ERANGE || memory == 0) {
793 conn->error_code = http_internal_error;
794 return ret_error;
798 ret = cherokee_avl_get_ptr (conn->arguments, "interface", &temp);
799 if (ret == ret_ok)
800 interface = strtoul(temp, (char **) NULL, 10);
802 if (ret != ret_ok || errno == ERANGE) {
803 conn->error_code = http_internal_error;
804 return ret_error;
807 cherokee_buffer_t domu = CHEROKEE_BUF_INIT;
808 cherokee_buffer_add_va (&domu, "%s_%s", hdl->user.buf, hdl->vm.buf);
810 for (i = 0; i < interface; i++) {
811 char *mac = NULL;
812 char *ip = NULL;
813 if (getNewMac("dv28", domu.buf, &mac, &ip) == 0)
814 cherokee_buffer_add_va (&xml_interfaces, VIRT_INTERFACE_XML, mac, ip);
817 cherokee_buffer_mrproper(&domu);
819 cherokee_buffer_add_va (&xml, VIRT_DOMAIN_XML,
820 hdl->user.buf, hdl->vm.buf, memory, vcpu, xml_interfaces.buf);
822 cherokee_buffer_mrproper(&xml_interfaces);
823 break;
826 case storageVolCreateXML:
827 case domainDefineXML: {
828 off_t postl;
829 cherokee_post_get_len (&conn->post, &postl);
830 cherokee_post_walk_read (&conn->post, &xml, (cuint_t) postl);
831 break;
835 switch (hdl->action) {
836 case domainDefineXML_args:
837 case domainDefineXML: {
838 result = virDomainDefineXML(virConn, (const char *) xml.buf);
839 // printf("%s\n", xml.buf);
840 cherokee_buffer_mrproper(&xml);
842 if (result == NULL) {
843 /* TODO: vrij maken eventuele uitgegeven macs! */
844 conn->error_code = http_internal_error;
845 return ret_error;
848 cherokee_buffer_t path = CHEROKEE_BUF_INIT;
849 cherokee_buffer_add_va (&path, "/mnt/netapp/users/%s", hdl->user.buf);
851 mkdir(path.buf, 0755);
853 cherokee_buffer_add_va (&path, "/%s", hdl->vm.buf);
855 mkdir(path.buf, 0755);
857 cherokee_buffer_add_str (&path, "/index.xml");
859 FILE *fd;
860 if ((fd = fopen(path.buf, "w")) == NULL) {
861 printf("%s\n", path.buf);
862 /* eigenlijk alles opschonen... */
863 conn->error_code = http_internal_error;
864 return ret_error;
865 } else {
866 char *output = virDomainGetXMLDesc(result, 0);
867 fwrite(output, strlen(output), sizeof(char), fd);
868 fclose(fd);
869 cherokee_buffer_add(buf, output, strlen(output));
870 free(output);
873 cherokee_buffer_mrproper(&path);
875 break;
878 case storageVolCreateXML_args:
879 case storageVolCreateXML: {
880 virStorageVolPtr vol = virStorageVolCreateXML(pool, xml.buf, 0);
881 virStoragePoolFree(pool);
882 cherokee_buffer_mrproper(&xml);
884 if (vol == NULL) {
885 cherokee_buffer_add_long10(buf, -1);
886 return ret_error;
889 cherokee_buffer_add_long10(buf, 0);
890 break;
894 return ret_ok;
898 static ret_t
899 virt_virt_do(cherokee_handler_virt_t *hdl, cherokee_buffer_t *domu, cherokee_buffer_t *uri)
901 cherokee_connection_t *conn = HANDLER_CONN(hdl);
903 ret_t ret = ret_error;
904 virConnectPtr virConn = NULL;
907 if (HDL_VIRT_PROPS(hdl)->read_only == FALSE)
908 virConn = virConnectOpen (uri->buf);
910 if (!virConn && !(virConn = virConnectOpenReadOnly (uri->buf))) {
911 conn->error_code = http_service_unavailable;
912 return ret_error;
915 switch (hdl->action) {
916 case storageVolGetXMLDesc:
917 case storageVolCloneXML_args:
918 case storageVolCreateXML_args:
919 case storageVolCreateXML:
920 case domainDefineXML_args:
921 case domainDefineXML: {
922 ret = virt_virt_new(hdl, virConn);
923 break;
926 default: {
927 virDomainPtr dom;
928 if ((dom = virDomainLookupByName(virConn, domu->buf)) == NULL) {
929 conn->error_code = http_not_found;
930 } else {
931 ret = virt_virt_function(hdl, dom);
932 virDomainFree(dom);
937 virConnectClose(virConn);
938 return ret;
941 static ret_t
942 virt_while (cherokee_buffer_t *key, void *value, void *param) {
943 cherokee_handler_virt_t * hdl = param;
944 // cherokee_buffer_t uri = CHEROKEE_BUF_INIT;
945 // cherokee_buffer_add_va (&uri, "xen://%s/", ((cherokee_buffer_t *) value)->buf);
946 // virt_virt_do((cherokee_handler_virt_t *) param, key, &uri);
947 // cherokee_buffer_mrproper(&uri);
949 cherokee_buffer_add_va (&hdl->buffer, "<domain><name>%s</name></domain>", key->buf);
951 return ret_ok;
954 static ret_t
955 virt_while_user (cherokee_buffer_t *key, void *value, void *param) {
956 cherokee_handler_virt_t *hdl = param;
957 if (key->len > hdl->user.len && key->buf[hdl->user.len] == '_' && strncmp(key->buf, hdl->user.buf, hdl->user.len) == 0)
958 return virt_while (key, value, param);
960 return ret_ok;
963 static ret_t
964 virt_build_page (cherokee_handler_virt_t *hdl)
966 ret_t ret;
967 cherokee_connection_t *conn = HANDLER_CONN(hdl);
968 cherokee_buffer_t uri = CHEROKEE_BUF_INIT;
969 cherokee_buffer_t domu = CHEROKEE_BUF_INIT;
971 if (hdl->action > xml && HDL_VIRT_PROPS(hdl)->xsl.len > 0)
972 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);
975 /* First, block the event loop */
976 avahi_threaded_poll_lock(HDL_AVAHI_PROPS(hdl)->threaded_poll);
977 switch (hdl->action) {
978 case showall:
979 cherokee_buffer_add_str (&hdl->buffer, "<domains>");
980 cherokee_avl_while(&HDL_AVAHI_PROPS(hdl)->entries, virt_while, hdl, NULL, NULL);
981 cherokee_buffer_add_str (&hdl->buffer, "</domains>");
982 ret = ret_ok;
983 break;
985 case showuservms: {
986 void *param[3];
987 cherokee_buffer_add_str (&hdl->buffer, "<domains>");
988 cherokee_avl_while(&HDL_AVAHI_PROPS(hdl)->entries, virt_while_user, hdl, NULL, NULL);
989 cherokee_buffer_add_str (&hdl->buffer, "</domains>");
990 ret = ret_ok;
991 break;
994 default: {
995 cherokee_buffer_t *hostname = NULL;
996 cherokee_buffer_add_va (&domu, "%s_%s", hdl->user.buf, hdl->vm.buf);
997 ret = cherokee_avl_get_ptr(&HDL_AVAHI_PROPS(hdl)->entries, domu.buf, (void **) &hostname);
999 if (ret == ret_not_found) {
1000 virDomainPtr virDom;
1001 virConnectPtr virConn;
1002 cherokee_buffer_add_va (&uri, "xen://%s/", HDL_VIRT_PROPS(hdl)->virt); // TODO: change!
1004 if (HDL_VIRT_PROPS(hdl)->read_only == FALSE)
1005 virConn = virConnectOpen (uri.buf);
1007 if (!virConn && !(virConn = virConnectOpenReadOnly (uri.buf))) {
1008 conn->error_code = http_service_unavailable;
1009 return ret_error;
1012 if ((virDom = virDomainLookupByName(virConn, domu.buf)) == NULL) {
1013 if (hdl->action != domainDefineXML_args && hdl->action != domainDefineXML) {
1014 hdl->action = nothing;
1015 conn->error_code = http_not_found;
1016 ret = ret_error;
1017 } else {
1018 ret = ret_ok;
1020 } else {
1021 virDomainFree(virDom);
1022 ret = ret_ok;
1024 virConnectClose (virConn);
1025 } else if (ret == ret_ok) {
1026 cherokee_buffer_add_va (&uri, "xen://%s/", hostname->buf);
1027 printf("%s\n", uri.buf);
1028 } else {
1029 hdl->action = http_internal_error;
1030 hdl->action = nothing;
1031 ret = ret_error;
1036 /* Finally, unblock the event loop */
1037 avahi_threaded_poll_unlock(HDL_AVAHI_PROPS(hdl)->threaded_poll);
1039 if (ret == ret_ok && hdl->action != showall && hdl->action != showuservms) {
1040 ret = virt_virt_do(hdl, &domu, &uri);
1043 cherokee_buffer_mrproper(&domu);
1044 cherokee_buffer_mrproper(&uri);
1047 return ret;
1051 ret_t
1052 cherokee_handler_virt_new (cherokee_handler_t **hdl, cherokee_connection_t *cnt, cherokee_module_props_t *props)
1054 ret_t ret;
1055 CHEROKEE_NEW_STRUCT (n, handler_virt);
1057 /* Init the base class
1060 cherokee_handler_init_base(HANDLER(n), cnt, HANDLER_PROPS(props), PLUGIN_INFO_HANDLER_PTR(virt));
1062 MODULE(n)->init = (handler_func_init_t) cherokee_handler_virt_init;
1063 MODULE(n)->free = (module_func_free_t) cherokee_handler_virt_free;
1064 HANDLER(n)->step = (handler_func_step_t) cherokee_handler_virt_step;
1065 HANDLER(n)->add_headers = (handler_func_add_headers_t) cherokee_handler_virt_add_headers;
1067 HANDLER(n)->support = hsupport_length | hsupport_range;
1069 ret = cherokee_buffer_init (&n->buffer);
1070 if (unlikely(ret != ret_ok))
1071 return ret;
1073 ret = cherokee_buffer_ensure_size (&n->buffer, 4*1024);
1074 if (unlikely(ret != ret_ok))
1075 return ret;
1077 *hdl = HANDLER(n);
1079 return ret_ok;