Merge lp:~smoser/ubuntu/maverick/eucalyptus/maverick.bug611144 into lp:ubuntu/maverick/eucalyptus
- Maverick (10.10)
- maverick.bug611144
- Merge into maverick
Proposed by
Scott Moser
Status: | Merged |
---|---|
Merge reported by: | Thierry Carrez |
Merged at revision: | not available |
Proposed branch: | lp:~smoser/ubuntu/maverick/eucalyptus/maverick.bug611144 |
Merge into: | lp:ubuntu/maverick/eucalyptus |
Diff against target: |
2160 lines (+1986/-9) 15 files modified
.pc/22-uec-multiboot-kvm.patch/node/handlers.c (+1227/-0) .pc/22-uec-multiboot-kvm.patch/tools/Makefile (+71/-0) .pc/22-uec-multiboot-kvm.patch/tools/gen_kvm_libvirt_xml (+165/-0) .pc/22-uec-multiboot-kvm.patch/util/wrappers.conf (+51/-0) .pc/applied-patches (+1/-0) debian/changelog (+6/-0) debian/control (+4/-1) debian/eucalyptus-nc.install (+1/-0) debian/patches/22-uec-multiboot-kvm.patch (+292/-0) debian/patches/series (+1/-0) node/handlers.c (+4/-0) tools/Makefile (+2/-0) tools/gen_kvm_libvirt_xml (+47/-8) tools/mk-mb-loader (+113/-0) util/wrappers.conf (+1/-0) |
To merge this branch: | bzr merge lp:~smoser/ubuntu/maverick/eucalyptus/maverick.bug611144 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Dave Walker (community) | Approve | ||
Ubuntu branches | Pending | ||
Review via email: mp+31249@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
- 159. By Scott Moser
-
fix 2 issues with floppy/multiboot booting in gen_kvm_libvirt_xml
2 issues are corrected here.
1.) closing tag is needed in 'boot' tag
2.) if '<boot dev='hd/>' is not present, then scsi disks will not
get the kvm parameter 'boot=on'. Without that, the boot floppy
will not see the disk.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory '.pc/22-uec-multiboot-kvm.patch' |
2 | === added file '.pc/22-uec-multiboot-kvm.patch/.timestamp' |
3 | === added directory '.pc/22-uec-multiboot-kvm.patch/node' |
4 | === added file '.pc/22-uec-multiboot-kvm.patch/node/handlers.c' |
5 | --- .pc/22-uec-multiboot-kvm.patch/node/handlers.c 1970-01-01 00:00:00 +0000 |
6 | +++ .pc/22-uec-multiboot-kvm.patch/node/handlers.c 2010-07-30 21:11:15 +0000 |
7 | @@ -0,0 +1,1227 @@ |
8 | +/* |
9 | +Copyright (c) 2009 Eucalyptus Systems, Inc. |
10 | + |
11 | +This program is free software: you can redistribute it and/or modify |
12 | +it under the terms of the GNU General Public License as published by |
13 | +the Free Software Foundation, only version 3 of the License. |
14 | + |
15 | +This file is distributed in the hope that it will be useful, but WITHOUT |
16 | +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
17 | +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
18 | +for more details. |
19 | + |
20 | +You should have received a copy of the GNU General Public License along |
21 | +with this program. If not, see <http://www.gnu.org/licenses/>. |
22 | + |
23 | +Please contact Eucalyptus Systems, Inc., 130 Castilian |
24 | +Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/> |
25 | +if you need additional information or have any questions. |
26 | + |
27 | +This file may incorporate work covered under the following copyright and |
28 | +permission notice: |
29 | + |
30 | + Software License Agreement (BSD License) |
31 | + |
32 | + Copyright (c) 2008, Regents of the University of California |
33 | + |
34 | + |
35 | + Redistribution and use of this software in source and binary forms, with |
36 | + or without modification, are permitted provided that the following |
37 | + conditions are met: |
38 | + |
39 | + Redistributions of source code must retain the above copyright notice, |
40 | + this list of conditions and the following disclaimer. |
41 | + |
42 | + Redistributions in binary form must reproduce the above copyright |
43 | + notice, this list of conditions and the following disclaimer in the |
44 | + documentation and/or other materials provided with the distribution. |
45 | + |
46 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
47 | + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
48 | + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
49 | + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER |
50 | + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
51 | + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
52 | + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
53 | + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
54 | + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
55 | + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
56 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF |
57 | + THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE |
58 | + LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS |
59 | + SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING |
60 | + IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA |
61 | + BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN |
62 | + THE REGENTS’ DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT |
63 | + OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR |
64 | + WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH |
65 | + ANY SUCH LICENSES OR RIGHTS. |
66 | +*/ |
67 | +#include <stdio.h> |
68 | +#include <stdlib.h> |
69 | +#define __USE_GNU |
70 | +#include <string.h> /* strlen, strcpy */ |
71 | +#include <time.h> |
72 | +#include <limits.h> /* INT_MAX */ |
73 | +#include <sys/types.h> /* fork */ |
74 | +#include <sys/wait.h> /* waitpid */ |
75 | +#include <unistd.h> |
76 | +#include <fcntl.h> |
77 | +#include <assert.h> |
78 | +#include <errno.h> |
79 | +#define _FILE_OFFSET_BITS 64 |
80 | +#include <sys/stat.h> |
81 | +#include <pthread.h> |
82 | +#include <sys/vfs.h> /* statfs */ |
83 | +#include <signal.h> /* SIGINT */ |
84 | +#include <linux/limits.h> |
85 | +#ifndef MAX_PATH |
86 | +#define MAX_PATH 4096 |
87 | +#endif |
88 | + |
89 | +#include "eucalyptus-config.h" |
90 | +#include "ipc.h" |
91 | +#include "misc.h" |
92 | +#define HANDLERS_FANOUT |
93 | +#include <handlers.h> |
94 | +#include <storage.h> |
95 | +#include <eucalyptus.h> |
96 | + |
97 | +#define MONITORING_PERIOD (5) |
98 | + |
99 | +/* used by lower level handlers */ |
100 | +sem *hyp_sem; /* semaphore for serializing domain creation */ |
101 | +sem *inst_sem; /* guarding access to global instance structs */ |
102 | +sem *addkey_sem; /* guarding access to global instance structs */ |
103 | + |
104 | +bunchOfInstances *global_instances = NULL; |
105 | + |
106 | +// declarations of available handlers |
107 | +extern struct handlers xen_libvirt_handlers; |
108 | +extern struct handlers kvm_libvirt_handlers; |
109 | +extern struct handlers default_libvirt_handlers; |
110 | + |
111 | +const int staging_cleanup_threshold = 60 * 60 * 2; /* after this many seconds any STAGING domains will be cleaned up */ |
112 | +const int booting_cleanup_threshold = 60; /* after this many seconds any BOOTING domains will be cleaned up */ |
113 | +const int teardown_state_duration = 180; /* after this many seconds in TEARDOWN state (no resources), we'll forget about the instance */ |
114 | + |
115 | +// a NULL-terminated array of available handlers |
116 | +static struct handlers * available_handlers [] = { |
117 | + &default_libvirt_handlers, |
118 | + &xen_libvirt_handlers, |
119 | + &kvm_libvirt_handlers, |
120 | + NULL |
121 | +}; |
122 | + |
123 | +struct nc_state_t nc_state; |
124 | + |
125 | +/* utilitarian functions used in the lower level handlers */ |
126 | +int |
127 | +get_value( char *s, |
128 | + const char *name, |
129 | + long long * valp) |
130 | +{ |
131 | + char buf [CHAR_BUFFER_SIZE]; |
132 | + |
133 | + if (s==NULL || name==NULL || valp==NULL) |
134 | + return ERROR; |
135 | + snprintf (buf, CHAR_BUFFER_SIZE, "%s=%%lld", name); |
136 | + return (sscanf_lines (s, buf, valp)==1 ? OK : ERROR); |
137 | +} |
138 | + |
139 | +void libvirt_error_handler ( void *userData, |
140 | + virErrorPtr error) |
141 | +{ |
142 | + if ( error==NULL) { |
143 | + logprintfl (EUCAERROR, "libvirt error handler was given a NULL pointer\n"); |
144 | + } else { |
145 | + logprintfl (EUCAERROR, "libvirt: %s (code=%d)\n", error->message, error->code); |
146 | + } |
147 | +} |
148 | + |
149 | +int convert_dev_names( char *localDev, |
150 | + char *localDevReal, |
151 | + char *localDevTag) |
152 | +{ |
153 | + bzero(localDevReal, 32); |
154 | + if (strchr(localDev, '/') != NULL) { |
155 | + sscanf(localDev, "/dev/%s", localDevReal); |
156 | + } else { |
157 | + snprintf(localDevReal, 32, "%s", localDev); |
158 | + } |
159 | + if (localDevReal[0] == 0) { |
160 | + logprintfl(EUCAERROR, "bad input parameter for localDev (should be /dev/XXX): '%s'\n", localDev); |
161 | + return(ERROR); |
162 | + } |
163 | + if (localDevTag) { |
164 | + bzero(localDevTag, 256); |
165 | + snprintf(localDevTag, 256, "unknown,requested:%s", localDev); |
166 | + } |
167 | + |
168 | + return 0; |
169 | +} |
170 | + |
171 | +void |
172 | +print_running_domains (void) |
173 | +{ |
174 | + bunchOfInstances * head; |
175 | + char buf [CHAR_BUFFER_SIZE] = ""; |
176 | + |
177 | + sem_p (inst_sem); |
178 | + for ( head=global_instances; head; head=head->next ) { |
179 | + ncInstance * instance = head->instance; |
180 | + if (instance->state==STAGING || instance->state==BOOTING |
181 | + || instance->state==RUNNING |
182 | + || instance->state==BLOCKED |
183 | + || instance->state==PAUSED) { |
184 | + strcat (buf, " "); |
185 | + strcat (buf, instance->instanceId); |
186 | + } |
187 | + } |
188 | + sem_v (inst_sem); |
189 | + logprintfl (EUCAINFO, "currently running/booting: %s\n", buf); |
190 | +} |
191 | + |
192 | +virConnectPtr * |
193 | +check_hypervisor_conn() |
194 | +{ |
195 | + if (nc_state.conn == NULL || virConnectGetURI(nc_state.conn) == NULL) { |
196 | + nc_state.conn = virConnectOpen (nc_state.uri); |
197 | + if (nc_state.conn == NULL) { |
198 | + logprintfl (EUCAFATAL, "Failed to connect to %s\n", nc_state.uri); |
199 | + return NULL; |
200 | + } |
201 | + } |
202 | + |
203 | + return &(nc_state.conn); |
204 | +} |
205 | + |
206 | + |
207 | +void change_state( ncInstance *instance, |
208 | + instance_states state) |
209 | +{ |
210 | + int old_state = instance->state; |
211 | + instance->state = (int) state; |
212 | + switch (state) { /* mapping from NC's internal states into external ones */ |
213 | + case STAGING: |
214 | + case BOOTING: |
215 | + case CANCELED: |
216 | + instance->stateCode = PENDING; |
217 | + break; |
218 | + case RUNNING: |
219 | + case BLOCKED: |
220 | + case PAUSED: |
221 | + case SHUTDOWN: |
222 | + case SHUTOFF: |
223 | + case CRASHED: |
224 | + instance->stateCode = EXTANT; |
225 | + instance->retries = LIBVIRT_QUERY_RETRIES; |
226 | + break; |
227 | + case TEARDOWN: |
228 | + instance->stateCode = TEARDOWN; |
229 | + break; |
230 | + default: |
231 | + logprintfl (EUCAERROR, "error: change_sate(): unexpected state (%d) for instance %s\n", instance->state, instance->instanceId); |
232 | + return; |
233 | + } |
234 | + |
235 | + strncpy(instance->stateName, instance_state_names[instance->stateCode], CHAR_BUFFER_SIZE); |
236 | + if (old_state != state) { |
237 | + logprintfl (EUCADEBUG, "state change for instance %s: %s -> %s (%s)\n", |
238 | + instance->instanceId, |
239 | + instance_state_names [old_state], |
240 | + instance_state_names [instance->state], |
241 | + instance_state_names [instance->stateCode]); |
242 | + } |
243 | +} |
244 | + |
245 | +// waits indefinitely until a state transition takes place |
246 | +// (timeouts are implemented in the monitoring thread) and |
247 | +// returns 0 if from_state->to_state transition takes place |
248 | +// and 1 otherwise |
249 | +int |
250 | +wait_state_transition (ncInstance * instance, |
251 | + instance_states from_state, |
252 | + instance_states to_state) |
253 | +{ |
254 | + while (1) { |
255 | + instance_states current_state = instance->state; |
256 | + if (current_state == to_state ) |
257 | + return 0; |
258 | + if (current_state != from_state ) |
259 | + return 1; |
260 | + sleep (MONITORING_PERIOD); // no point in checking more frequently |
261 | + } |
262 | +} |
263 | + |
264 | +static void |
265 | +refresh_instance_info( struct nc_state_t *nc, |
266 | + ncInstance *instance) |
267 | +{ |
268 | + int now = instance->state; |
269 | + |
270 | + if (! check_hypervisor_conn ()) |
271 | + return; |
272 | + |
273 | + /* no need to bug for domains without state on Hypervisor */ |
274 | + if (now==TEARDOWN || now==STAGING) |
275 | + return; |
276 | + |
277 | + sem_p(hyp_sem); |
278 | + virDomainPtr dom = virDomainLookupByName (nc_state.conn, instance->instanceId); |
279 | + sem_v(hyp_sem); |
280 | + if (dom == NULL) { /* hypervisor doesn't know about it */ |
281 | + if (now==RUNNING || |
282 | + now==BLOCKED || |
283 | + now==PAUSED || |
284 | + now==SHUTDOWN) { |
285 | + /* Most likely the user has shut it down from the inside */ |
286 | + if (instance->retries) { |
287 | + instance->retries--; |
288 | + logprintfl (EUCAWARN, "warning: hypervisor failed to find domain %s, will retry %d more times\n", instance->instanceId, instance->retries); |
289 | + } else { |
290 | + logprintfl (EUCAWARN, "warning: hypervisor failed to find domain %s, assuming it was shut off\n", instance->instanceId); |
291 | + change_state (instance, SHUTOFF); |
292 | + } |
293 | + } |
294 | + /* else 'now' stays in SHUTFOFF, BOOTING, CANCELED, or CRASHED */ |
295 | + return; |
296 | + } |
297 | + virDomainInfo info; |
298 | + sem_p(hyp_sem); |
299 | + int error = virDomainGetInfo(dom, &info); |
300 | + sem_v(hyp_sem); |
301 | + if (error < 0 || info.state == VIR_DOMAIN_NOSTATE) { |
302 | + logprintfl (EUCAWARN, "warning: failed to get informations for domain %s\n", instance->instanceId); |
303 | + /* what to do? hopefully we'll find out more later */ |
304 | + sem_p(hyp_sem); |
305 | + virDomainFree (dom); |
306 | + sem_v(hyp_sem); |
307 | + return; |
308 | + } |
309 | + int xen = info.state; |
310 | + |
311 | + switch (now) { |
312 | + case BOOTING: |
313 | + case RUNNING: |
314 | + case BLOCKED: |
315 | + case PAUSED: |
316 | + /* change to state, whatever it happens to be */ |
317 | + change_state (instance, xen); |
318 | + break; |
319 | + case SHUTDOWN: |
320 | + case SHUTOFF: |
321 | + case CRASHED: |
322 | + if (xen==RUNNING || |
323 | + xen==BLOCKED || |
324 | + xen==PAUSED) { |
325 | + /* cannot go back! */ |
326 | + logprintfl (EUCAWARN, "warning: detected prodigal domain %s, terminating it\n", instance->instanceId); |
327 | + sem_p (hyp_sem); |
328 | + virDomainDestroy (dom); |
329 | + sem_v (hyp_sem); |
330 | + } else { |
331 | + change_state (instance, xen); |
332 | + } |
333 | + break; |
334 | + default: |
335 | + logprintfl (EUCAERROR, "error: refresh...(): unexpected state (%d) for instance %s\n", now, instance->instanceId); |
336 | + return; |
337 | + } |
338 | + sem_p(hyp_sem); |
339 | + virDomainFree(dom); |
340 | + sem_v(hyp_sem); |
341 | + |
342 | + /* if instance is running, try to find out its IP address */ |
343 | + if (instance->state==RUNNING || |
344 | + instance->state==BLOCKED || |
345 | + instance->state==PAUSED) { |
346 | + char *ip=NULL; |
347 | + int rc; |
348 | + |
349 | + if (!strncmp(instance->ncnet.publicIp, "0.0.0.0", 24)) { |
350 | + if (!strcmp(nc_state.vnetconfig->mode, "SYSTEM") || !strcmp(nc_state.vnetconfig->mode, "STATIC")) { |
351 | + rc = mac2ip(nc_state.vnetconfig, instance->ncnet.privateMac, &ip); |
352 | + if (!rc) { |
353 | + if(ip) { |
354 | + logprintfl (EUCAINFO, "discovered public IP %s for instance %s\n", ip, instance->instanceId); |
355 | + strncpy(instance->ncnet.publicIp, ip, 24); |
356 | + free(ip); |
357 | + } |
358 | + } |
359 | + } |
360 | + } |
361 | + if (!strncmp(instance->ncnet.privateIp, "0.0.0.0", 24)) { |
362 | + rc = mac2ip(nc_state.vnetconfig, instance->ncnet.privateMac, &ip); |
363 | + if (!rc) { |
364 | + if(ip) { |
365 | + logprintfl (EUCAINFO, "discovered private IP %s for instance %s\n", ip, instance->instanceId); |
366 | + strncpy(instance->ncnet.privateIp, ip, 24); |
367 | + free(ip); |
368 | + } |
369 | + } |
370 | + } |
371 | + } |
372 | +} |
373 | + |
374 | +int |
375 | +get_instance_xml( const char *gen_libvirt_cmd_path, |
376 | + char *userId, |
377 | + char *instanceId, |
378 | + char *ramdiskId, |
379 | + char *kernelId, |
380 | + char *disk_path, |
381 | + virtualMachine *params, |
382 | + char *privMac, |
383 | + // char *privIp, |
384 | + char *brname, |
385 | + int use_virtio_net, |
386 | + int use_virtio_root, |
387 | + char **xml) |
388 | +{ |
389 | + char buf [MAX_PATH]; |
390 | + |
391 | + snprintf(buf, MAX_PATH, "%s", gen_libvirt_cmd_path); |
392 | + if (strnlen(ramdiskId, CHAR_BUFFER_SIZE)) { |
393 | + strncat(buf, " --ramdisk", MAX_PATH); |
394 | + } |
395 | + if (use_virtio_net) { |
396 | + strncat(buf, " --virtionet", MAX_PATH); |
397 | + } |
398 | + if (use_virtio_root) { |
399 | + strncat(buf, " --virtioroot", MAX_PATH); |
400 | + } |
401 | + |
402 | + if (params->disk > 0) { /* TODO: get this info from scMakeImage */ |
403 | + strncat (buf, " --ephemeral", MAX_PATH); |
404 | + } |
405 | + * xml = system_output (buf); |
406 | + if ( ( * xml ) == NULL ) { |
407 | + logprintfl (EUCAFATAL, "%s: %s\n", gen_libvirt_cmd_path, strerror (errno)); |
408 | + return ERROR; |
409 | + } |
410 | + |
411 | + /* the tags better be not substring of other tags: BA will substitute |
412 | + * ABABABAB */ |
413 | + replace_string (xml, "BASEPATH", disk_path); |
414 | + replace_string (xml, "SWAPPATH", disk_path); |
415 | + replace_string (xml, "NAME", instanceId); |
416 | + replace_string (xml, "PRIVMACADDR", privMac); |
417 | + // replace_string (xml, "PUBMACADDR", pubMac); |
418 | + replace_string (xml, "BRIDGEDEV", brname); |
419 | + snprintf(buf, CHAR_BUFFER_SIZE, "%d", params->mem * 1024); /* because libvirt wants memory in Kb, while we use Mb */ |
420 | + replace_string (xml, "MEMORY", buf); |
421 | + snprintf(buf, CHAR_BUFFER_SIZE, "%d", params->cores); |
422 | + replace_string (xml, "VCPUS", buf); |
423 | + |
424 | + return 0; |
425 | +} |
426 | + |
427 | + |
428 | +void * |
429 | +monitoring_thread (void *arg) |
430 | +{ |
431 | + int i; |
432 | + struct nc_state_t *nc; |
433 | + |
434 | + if (arg == NULL) { |
435 | + logprintfl (EUCAFATAL, "NULL parameter!\n"); |
436 | + return NULL; |
437 | + } |
438 | + nc = (struct nc_state_t*)arg; |
439 | + |
440 | + logprintfl (EUCADEBUG, "Starting monitoring thread\n!\n"); |
441 | + |
442 | + for (;;) { |
443 | + bunchOfInstances *head; |
444 | + time_t now = time(NULL); |
445 | + sem_p (inst_sem); |
446 | + |
447 | + for ( head = global_instances; head; head = head->next ) { |
448 | + ncInstance * instance = head->instance; |
449 | + |
450 | + /* query for current state, if any */ |
451 | + refresh_instance_info (nc, instance); |
452 | + |
453 | + /* don't touch running or canceled threads */ |
454 | + if (instance->state!=STAGING && instance->state!=BOOTING && |
455 | + instance->state!=SHUTOFF && |
456 | + instance->state!=SHUTDOWN && |
457 | + instance->state!=TEARDOWN) continue; |
458 | + |
459 | + if (instance->state==TEARDOWN) { |
460 | + /* it's been long enough, we can forget the instance */ |
461 | + if ((now - instance->terminationTime)>teardown_state_duration) { |
462 | + remove_instance (&global_instances, instance); |
463 | + logprintfl (EUCAINFO, "forgetting about instance %s\n", instance->instanceId); |
464 | + free_instance (&instance); |
465 | + break; /* need to get out since the list changed */ |
466 | + } |
467 | + continue; |
468 | + } |
469 | + |
470 | + // time out logic for STAGING or BOOTING instances |
471 | + if (instance->state==STAGING |
472 | + && (now - instance->launchTime) < staging_cleanup_threshold) continue; // hasn't been long enough, spare it |
473 | + if (instance->state==BOOTING |
474 | + && (now - instance->bootTime) < booting_cleanup_threshold) continue; |
475 | + |
476 | + /* ok, it's been condemned => destroy the files */ |
477 | + if (!nc_state.save_instance_files) { |
478 | + logprintfl (EUCAINFO, "cleaning up state for instance %s\n", instance->instanceId); |
479 | + if (scCleanupInstanceImage(instance->userId, instance->instanceId)) { |
480 | + logprintfl (EUCAWARN, "warning: failed to cleanup instance image %s\n", instance->instanceId); |
481 | + } |
482 | + } else { |
483 | + logprintfl (EUCAINFO, "cleaning up state for instance %s (but keeping the files)\n", instance->instanceId); |
484 | + } |
485 | + |
486 | + /* check to see if this is the last instance running on vlan */ |
487 | + int left = 0; |
488 | + bunchOfInstances * vnhead; |
489 | + for (vnhead = global_instances; vnhead; vnhead = vnhead->next ) { |
490 | + ncInstance * vninstance = vnhead->instance; |
491 | + if (vninstance->ncnet.vlan == (instance->ncnet).vlan |
492 | + && strcmp(instance->instanceId, vninstance->instanceId)) { |
493 | + left++; |
494 | + } |
495 | + } |
496 | + if (left==0) { |
497 | + logprintfl (EUCAINFO, "stopping the network (vlan=%d)\n", (instance->ncnet).vlan); |
498 | + vnetStopNetwork (nc_state.vnetconfig, (instance->ncnet).vlan, NULL, NULL); |
499 | + } |
500 | + change_state (instance, TEARDOWN); /* TEARDOWN = no more resources */ |
501 | + instance->terminationTime = time (NULL); |
502 | + } |
503 | + sem_v (inst_sem); |
504 | + |
505 | + if (head) { |
506 | + /* we got out because of modified list, no need to sleep |
507 | + * now */ |
508 | + continue; |
509 | + } |
510 | + |
511 | + sleep (MONITORING_PERIOD); |
512 | + } |
513 | + |
514 | + return NULL; |
515 | +} |
516 | + |
517 | + |
518 | +void *startup_thread (void * arg) |
519 | +{ |
520 | + ncInstance * instance = (ncInstance *)arg; |
521 | + virDomainPtr dom = NULL; |
522 | + char * disk_path, * xml=NULL; |
523 | + char *brname=NULL; |
524 | + int error, i; |
525 | + |
526 | + if (! check_hypervisor_conn ()) { |
527 | + logprintfl (EUCAFATAL, "could not start instance %s, abandoning it\n", instance->instanceId); |
528 | + change_state (instance, SHUTOFF); |
529 | + return NULL; |
530 | + } |
531 | + |
532 | + error = vnetStartNetwork (nc_state.vnetconfig, instance->ncnet.vlan, NULL, NULL, &brname); |
533 | + if ( error ) { |
534 | + logprintfl (EUCAFATAL, "start network failed for instance %s, terminating it\n", instance->instanceId); |
535 | + change_state (instance, SHUTOFF); |
536 | + return NULL; |
537 | + } |
538 | + logprintfl (EUCAINFO, "network started for instance %s\n", instance->instanceId); |
539 | + |
540 | + error = scMakeInstanceImage (nc_state.home, |
541 | + instance->userId, |
542 | + instance->imageId, instance->imageURL, |
543 | + instance->kernelId, instance->kernelURL, |
544 | + instance->ramdiskId, instance->ramdiskURL, |
545 | + instance->instanceId, instance->keyName, |
546 | + &disk_path, |
547 | + addkey_sem, nc_state.convert_to_disk, |
548 | + instance->params.disk*1024); |
549 | + if (error) { |
550 | + logprintfl (EUCAFATAL, "Failed to prepare images for instance %s (error=%d)\n", instance->instanceId, error); |
551 | + change_state (instance, SHUTOFF); |
552 | + if (brname) free(brname); |
553 | + return NULL; |
554 | + } |
555 | + if (instance->state==TEARDOWN) { // timed out in STAGING |
556 | + if (brname) free(brname); |
557 | + return NULL; |
558 | + } |
559 | + if (instance->state==CANCELED) { |
560 | + logprintfl (EUCAFATAL, "Startup of instance %s was cancelled\n", instance->instanceId); |
561 | + change_state (instance, SHUTOFF); |
562 | + if (brname) free(brname); |
563 | + return NULL; |
564 | + } |
565 | + |
566 | + error = get_instance_xml (nc_state.gen_libvirt_cmd_path, |
567 | + instance->userId, instance->instanceId, |
568 | + instance->ramdiskId, |
569 | + instance->kernelId, |
570 | + disk_path, |
571 | + &(instance->params), |
572 | + instance->ncnet.privateMac, |
573 | + brname, |
574 | + nc_state.config_use_virtio_net, |
575 | + nc_state.config_use_virtio_root, |
576 | + &xml); |
577 | + |
578 | + if (brname) free(brname); |
579 | + if (xml) logprintfl (EUCADEBUG2, "libvirt XML config:\n%s\n", xml); |
580 | + if (error) { |
581 | + logprintfl (EUCAFATAL, "Failed to create libvirt XML config for instance %s\n", instance->instanceId); |
582 | + change_state (instance, SHUTOFF); |
583 | + return NULL; |
584 | + } |
585 | + |
586 | + scStoreStringToInstanceFile (instance->userId, instance->instanceId, "libvirt.xml", xml); /* for debugging */ |
587 | + scSaveInstanceInfo(instance); /* to enable NC recovery */ |
588 | + |
589 | + /* we serialize domain creation as hypervisors can get confused with |
590 | + * too many simultaneous create requests */ |
591 | + logprintfl (EUCADEBUG2, "about to start domain %s\n", instance->instanceId); |
592 | + print_running_domains (); |
593 | + for (i=0; i<5 && dom == NULL; i++) { |
594 | + sem_p (hyp_sem); |
595 | + dom = virDomainCreateLinux (nc_state.conn, xml, 0); |
596 | + sem_v (hyp_sem); |
597 | + } |
598 | + if (xml) free(xml); |
599 | + if (dom == NULL) { |
600 | + logprintfl (EUCAFATAL, "hypervisor failed to start domain\n"); |
601 | + change_state (instance, SHUTOFF); |
602 | + return NULL; |
603 | + } |
604 | + eventlog("NC", instance->userId, "", "instanceBoot", "begin"); // TODO: bring back correlationId |
605 | + |
606 | + sem_p(hyp_sem); |
607 | + virDomainFree(dom); |
608 | + sem_v(hyp_sem); |
609 | + |
610 | + sem_p (inst_sem); |
611 | + // check one more time for cancellation |
612 | + if (instance->state==TEARDOWN) { |
613 | + // timed out in BOOTING |
614 | + } else if (instance->state==CANCELED || instance->state==SHUTOFF) { |
615 | + logprintfl (EUCAFATAL, "startup of instance %s was cancelled\n", instance->instanceId); |
616 | + change_state (instance, SHUTOFF); |
617 | + } else { |
618 | + logprintfl (EUCAINFO, "booting VM instance %s\n", instance->instanceId); |
619 | + instance->bootTime = time (NULL); |
620 | + change_state (instance, BOOTING); |
621 | + } |
622 | + sem_v (inst_sem); |
623 | + return NULL; |
624 | +} |
625 | + |
626 | +void adopt_instances() |
627 | +{ |
628 | + int dom_ids[MAXDOMS]; |
629 | + int num_doms = 0; |
630 | + int i; |
631 | + virDomainPtr dom = NULL; |
632 | + |
633 | + if (! check_hypervisor_conn()) |
634 | + return; |
635 | + |
636 | + logprintfl (EUCAINFO, "looking for existing domains\n"); |
637 | + virSetErrorFunc (NULL, libvirt_error_handler); |
638 | + |
639 | + num_doms = virConnectListDomains(nc_state.conn, dom_ids, MAXDOMS); |
640 | + if (num_doms == 0) { |
641 | + logprintfl (EUCAINFO, "no currently running domains to adopt\n"); |
642 | + return; |
643 | + } if (num_doms < 0) { |
644 | + logprintfl (EUCAWARN, "WARNING: failed to find out about running domains\n"); |
645 | + return; |
646 | + } |
647 | + |
648 | + for ( i=0; i<num_doms; i++) { |
649 | + int error; |
650 | + virDomainInfo info; |
651 | + const char * dom_name; |
652 | + ncInstance * instance; |
653 | + |
654 | + sem_p(hyp_sem); |
655 | + dom = virDomainLookupByID(nc_state.conn, dom_ids[i]); |
656 | + sem_v(hyp_sem); |
657 | + if (!dom) { |
658 | + logprintfl (EUCAWARN, "WARNING: failed to lookup running domain #%d, ignoring it\n", dom_ids[i]); |
659 | + continue; |
660 | + } |
661 | + |
662 | + sem_p(hyp_sem); |
663 | + error = virDomainGetInfo(dom, &info); |
664 | + sem_v(hyp_sem); |
665 | + if (error < 0 || info.state == VIR_DOMAIN_NOSTATE) { |
666 | + logprintfl (EUCAWARN, "WARNING: failed to get info on running domain #%d, ignoring it\n", dom_ids[i]); |
667 | + continue; |
668 | + } |
669 | + |
670 | + if (info.state == VIR_DOMAIN_SHUTDOWN || |
671 | + info.state == VIR_DOMAIN_SHUTOFF || |
672 | + info.state == VIR_DOMAIN_CRASHED ) { |
673 | + logprintfl (EUCADEBUG, "ignoring non-running domain #%d\n", dom_ids[i]); |
674 | + continue; |
675 | + } |
676 | + |
677 | + sem_p(hyp_sem); |
678 | + if ((dom_name = virDomainGetName(dom))==NULL) { |
679 | + sem_v(hyp_sem); |
680 | + logprintfl (EUCAWARN, "WARNING: failed to get name of running domain #%d, ignoring it\n", dom_ids[i]); |
681 | + continue; |
682 | + } |
683 | + sem_v(hyp_sem); |
684 | + |
685 | + if (!strcmp(dom_name, "Domain-0")) |
686 | + continue; |
687 | + |
688 | + if ((instance = scRecoverInstanceInfo (dom_name))==NULL) { |
689 | + logprintfl (EUCAWARN, "WARNING: failed to recover Eucalyptus metadata of running domain %s, ignoring it\n", dom_name); |
690 | + continue; |
691 | + } |
692 | + |
693 | + change_state (instance, info.state); |
694 | + sem_p (inst_sem); |
695 | + int err = add_instance (&global_instances, instance); |
696 | + sem_v (inst_sem); |
697 | + if (err) { |
698 | + free_instance (&instance); |
699 | + continue; |
700 | + } |
701 | + |
702 | + logprintfl (EUCAINFO, "- adopted running domain %s from user %s\n", instance->instanceId, instance->userId); |
703 | + /* TODO: try to look up IPs? */ |
704 | + |
705 | + sem_p(hyp_sem); |
706 | + virDomainFree (dom); |
707 | + sem_v(hyp_sem); |
708 | + } |
709 | +} |
710 | + |
711 | +static int init (void) |
712 | +{ |
713 | + static int initialized = 0; |
714 | + int do_warn = 0, i; |
715 | + char configFiles[2][MAX_PATH], |
716 | + log[MAX_PATH], |
717 | + *bridge, |
718 | + *hypervisor, |
719 | + *s, |
720 | + *tmp; |
721 | + struct stat mystat; |
722 | + struct statfs fs; |
723 | + struct handlers ** h; |
724 | + long long fs_free_blocks = 0; |
725 | + long long fs_block_size = 0; |
726 | + long long instances_bytes = 0; |
727 | + pthread_t tcb; |
728 | + |
729 | + if (initialized>0) /* 0 => hasn't run, -1 => failed, 1 => ok */ |
730 | + return 0; |
731 | + else if (initialized<0) |
732 | + return 1; |
733 | + |
734 | + bzero (&nc_state, sizeof(struct nc_state_t)); // ensure that MAXes are zeroed out |
735 | + |
736 | + /* from now on we have unrecoverable failure, so no point in |
737 | + * retrying to re-init */ |
738 | + initialized = -1; |
739 | + |
740 | + /* read in configuration - this should be first! */ |
741 | + tmp = getenv(EUCALYPTUS_ENV_VAR_NAME); |
742 | + if (!tmp) { |
743 | + nc_state.home[0] = '\0'; |
744 | + do_warn = 1; |
745 | + } else |
746 | + strncpy(nc_state.home, tmp, MAX_PATH); |
747 | + |
748 | + /* set the minimum log for now */ |
749 | + snprintf(log, MAX_PATH, "%s/var/log/eucalyptus/nc.log", nc_state.home); |
750 | + logfile(log, EUCADEBUG); |
751 | + |
752 | + if (do_warn) |
753 | + logprintfl (EUCAWARN, "env variable %s not set, using /\n", EUCALYPTUS_ENV_VAR_NAME); |
754 | + |
755 | + /* search for the config file */ |
756 | + snprintf(configFiles[1], MAX_PATH, EUCALYPTUS_CONF_LOCATION, nc_state.home); |
757 | + if (stat(configFiles[1], &mystat)) { |
758 | + logprintfl (EUCAFATAL, "could not open configuration file %s\n", configFiles[1]); |
759 | + return 1; |
760 | + } |
761 | + snprintf(configFiles[0], MAX_PATH, EUCALYPTUS_CONF_OVERRIDE_LOCATION, nc_state.home); |
762 | + |
763 | + logprintfl (EUCAINFO, "NC is looking for configuration in %s,%s\n", configFiles[1], configFiles[0]); |
764 | + |
765 | + /* reset the log to the right value */ |
766 | + tmp = getConfString(configFiles, 2, "LOGLEVEL"); |
767 | + i = EUCADEBUG; |
768 | + if (tmp) { |
769 | + if (!strcmp(tmp,"INFO")) {i=EUCAINFO;} |
770 | + else if (!strcmp(tmp,"WARN")) {i=EUCAWARN;} |
771 | + else if (!strcmp(tmp,"ERROR")) {i=EUCAERROR;} |
772 | + else if (!strcmp(tmp,"FATAL")) {i=EUCAFATAL;} |
773 | + free(tmp); |
774 | + } |
775 | + logfile(log, i); |
776 | + |
777 | +#define GET_VAR_INT(var,name) \ |
778 | + s = getConfString(configFiles, 2, name); \ |
779 | + if (s){ \ |
780 | + var = atoi(s);\ |
781 | + free (s);\ |
782 | + } |
783 | + |
784 | + GET_VAR_INT(nc_state.config_max_mem, CONFIG_MAX_MEM); |
785 | + GET_VAR_INT(nc_state.config_max_disk, CONFIG_MAX_DISK); |
786 | + GET_VAR_INT(nc_state.config_max_cores, CONFIG_MAX_CORES); |
787 | + GET_VAR_INT(nc_state.save_instance_files, CONFIG_SAVE_INSTANCES); |
788 | + |
789 | + nc_state.config_network_port = NC_NET_PORT_DEFAULT; |
790 | + strcpy(nc_state.admin_user_id, EUCALYPTUS_ADMIN); |
791 | + |
792 | + hyp_sem = sem_alloc (1, "mutex"); |
793 | + inst_sem = sem_alloc (1, "mutex"); |
794 | + addkey_sem = sem_alloc (1, "mutex"); |
795 | + if (!hyp_sem || !inst_sem) { |
796 | + logprintfl (EUCAFATAL, "failed to create and initialize a semaphore\n"); |
797 | + return ERROR_FATAL; |
798 | + } |
799 | + |
800 | + /* set default in the paths. the driver will override */ |
801 | + nc_state.config_network_path[0] = '\0'; |
802 | + nc_state.gen_libvirt_cmd_path[0] = '\0'; |
803 | + nc_state.xm_cmd_path[0] = '\0'; |
804 | + nc_state.virsh_cmd_path[0] = '\0'; |
805 | + nc_state.get_info_cmd_path[0] = '\0'; |
806 | + snprintf (nc_state.rootwrap_cmd_path, MAX_PATH, EUCALYPTUS_ROOTWRAP, nc_state.home); |
807 | + |
808 | + /* prompt the SC to read the configuration too */ |
809 | + if (scInitConfig()) { |
810 | + logprintfl (EUCAFATAL, "ERROR: scInitConfig() failed\n"); |
811 | + return ERROR_FATAL; |
812 | + } |
813 | + |
814 | + /* determine the hypervisor to use */ |
815 | + |
816 | + //if (get_conf_var(config, CONFIG_HYPERVISOR, &hypervisor)<1) { |
817 | + hypervisor = getConfString(configFiles, 2, CONFIG_HYPERVISOR); |
818 | + if (!hypervisor) { |
819 | + logprintfl (EUCAFATAL, "value %s is not set in the config file\n", CONFIG_HYPERVISOR); |
820 | + return ERROR_FATAL; |
821 | + } |
822 | + |
823 | + /* let's look for the right hypervisor driver */ |
824 | + for (h = available_handlers; *h; h++ ) { |
825 | + if (!strncmp ((*h)->name, "default", CHAR_BUFFER_SIZE)) |
826 | + nc_state.D = *h; |
827 | + if (!strncmp ((*h)->name, hypervisor, CHAR_BUFFER_SIZE)) |
828 | + nc_state.H = *h; |
829 | + } |
830 | + if (nc_state.H == NULL) { |
831 | + logprintfl (EUCAFATAL, "requested hypervisor type (%s) is not available\n", hypervisor); |
832 | + free (hypervisor); |
833 | + return ERROR_FATAL; |
834 | + } |
835 | + |
836 | + /* only load virtio config for kvm */ |
837 | + if (!strncmp("kvm", hypervisor, CHAR_BUFFER_SIZE) || |
838 | + !strncmp("KVM", hypervisor, CHAR_BUFFER_SIZE)) { |
839 | + GET_VAR_INT(nc_state.config_use_virtio_net, CONFIG_USE_VIRTIO_NET); |
840 | + GET_VAR_INT(nc_state.config_use_virtio_disk, CONFIG_USE_VIRTIO_DISK); |
841 | + GET_VAR_INT(nc_state.config_use_virtio_root, CONFIG_USE_VIRTIO_ROOT); |
842 | + } |
843 | + |
844 | + free (hypervisor); |
845 | + |
846 | + /* NOTE: this is the only call which needs to be called on both |
847 | + * the default and the specific handler! All the others will be |
848 | + * either or */ |
849 | + i = nc_state.D->doInitialize(&nc_state); |
850 | + if (nc_state.H->doInitialize) |
851 | + i += nc_state.H->doInitialize(&nc_state); |
852 | + if (i) { |
853 | + logprintfl(EUCAFATAL, "ERROR: failed to initialized hypervisor driver!\n"); |
854 | + return ERROR_FATAL; |
855 | + } |
856 | + |
857 | + /* adopt running instances */ |
858 | + adopt_instances(); |
859 | + |
860 | + /* setup the network */ |
861 | + nc_state.vnetconfig = malloc(sizeof(vnetConfig)); |
862 | + if (!nc_state.vnetconfig) { |
863 | + logprintfl (EUCAFATAL, "Cannot allocate vnetconfig!\n"); |
864 | + return 1; |
865 | + } |
866 | + snprintf (nc_state.config_network_path, MAX_PATH, NC_NET_PATH_DEFAULT, nc_state.home); |
867 | + hypervisor = getConfString(configFiles, 2, "VNET_PUBINTERFACE"); |
868 | + if (!hypervisor) |
869 | + hypervisor = getConfString(configFiles, 2, "VNET_INTERFACE"); |
870 | + bridge = getConfString(configFiles, 2, "VNET_BRIDGE"); |
871 | + tmp = getConfString(configFiles, 2, "VNET_MODE"); |
872 | + |
873 | + vnetInit(nc_state.vnetconfig, tmp, nc_state.home, nc_state.config_network_path, NC, hypervisor, hypervisor, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, bridge, NULL, NULL); |
874 | + if (hypervisor) free(hypervisor); |
875 | + if (bridge) free(bridge); |
876 | + if (tmp) free(tmp); |
877 | + |
878 | + /* cleanup from previous runs and verify integrity of |
879 | + * instances directory */ |
880 | + sem_p (inst_sem); |
881 | + instances_bytes = scFSCK (&global_instances); |
882 | + sem_v (inst_sem); |
883 | + if (instances_bytes < 0) { |
884 | + logprintfl (EUCAFATAL, "instances store failed integrity check (error=%lld)\n", instances_bytes); |
885 | + return ERROR_FATAL; |
886 | + } |
887 | + |
888 | + /* get disk max */ |
889 | + strncpy(log, scGetInstancePath(), MAX_PATH); |
890 | + |
891 | + if (statfs(log, &fs) == -1) { |
892 | + logprintfl(EUCAWARN, "Failed to stat %s\n", log); |
893 | + } else { |
894 | + nc_state.disk_max = (long long)fs.f_bsize * (long long)fs.f_bavail + instances_bytes; /* max for Euca, not total */ |
895 | + nc_state.disk_max /= BYTES_PER_DISK_UNIT; |
896 | + if (nc_state.config_max_disk && nc_state.config_max_disk < nc_state.disk_max) |
897 | + nc_state.disk_max = nc_state.config_max_disk; |
898 | + |
899 | + logprintfl (EUCAINFO, "Maximum disk available: %lld (under %s)\n", nc_state.disk_max, log); |
900 | + } |
901 | + |
902 | + /* start the monitoring thread */ |
903 | + if (pthread_create(&tcb, NULL, monitoring_thread, &nc_state)) { |
904 | + logprintfl (EUCAFATAL, "failed to spawn a monitoring thread\n"); |
905 | + return ERROR_FATAL; |
906 | + } |
907 | + if (pthread_detach(tcb)) { |
908 | + logprintfl(EUCAFATAL, "failed to detach the monitoring thread\n"); |
909 | + return ERROR_FATAL; |
910 | + } |
911 | + |
912 | + |
913 | + initialized = 1; |
914 | + |
915 | + return OK; |
916 | +} |
917 | + |
918 | + |
919 | +int doDescribeInstances (ncMetadata *meta, char **instIds, int instIdsLen, ncInstance ***outInsts, int *outInstsLen) |
920 | +{ |
921 | + int ret, len, i; |
922 | + char *file_name; |
923 | + FILE *f; |
924 | + long long used_mem, used_disk, used_cores; |
925 | +#define NC_MONIT_FILENAME "/var/run/eucalyptus/nc-stats" |
926 | + |
927 | + if (init()) |
928 | + return 1; |
929 | + |
930 | + logprintfl(EUCADEBUG, "doDescribeInstances() invoked\n"); |
931 | + |
932 | + if (nc_state.H->doDescribeInstances) |
933 | + ret = nc_state.H->doDescribeInstances (&nc_state, meta, instIds, instIdsLen, outInsts, outInstsLen); |
934 | + else |
935 | + ret = nc_state.D->doDescribeInstances (&nc_state, meta, instIds, instIdsLen, outInsts, outInstsLen); |
936 | + |
937 | + if (ret) |
938 | + return ret; |
939 | + |
940 | + |
941 | + for (i=0; i < (*outInstsLen); i++) { |
942 | + ncInstance *instance = (*outInsts)[i]; |
943 | + logprintfl(EUCADEBUG, "doDescribeInstances(): instanceId=%s publicIp=%s privateIp=%s mac=%s vlan=%d networkIndex=%d \n", instance->instanceId, instance->ncnet.publicIp, instance->ncnet.privateIp, instance->ncnet.privateMac, instance->ncnet.vlan, instance->ncnet.networkIndex); |
944 | + } |
945 | + |
946 | + /* allocate enough memory */ |
947 | + len = (strlen(EUCALYPTUS_CONF_LOCATION) > strlen(NC_MONIT_FILENAME)) ? strlen(EUCALYPTUS_CONF_LOCATION) : strlen(NC_MONIT_FILENAME); |
948 | + len += 2 + strlen(nc_state.home); |
949 | + file_name = malloc(sizeof(char) * len); |
950 | + if (!file_name) { |
951 | + logprintfl(EUCAERROR, "Out of memory!\n"); |
952 | + return ret; |
953 | + } |
954 | + |
955 | + sprintf(file_name, "%s/%s", nc_state.home, NC_MONIT_FILENAME); |
956 | + if (!strcmp(meta->userId, EUCALYPTUS_ADMIN)) { |
957 | + f = fopen(file_name, "w"); |
958 | + if (!f) { |
959 | + f = fopen(file_name, "w+"); |
960 | + if (!f) |
961 | + logprintfl(EUCAWARN, "Cannot create %s!\n", file_name); |
962 | + else { |
963 | + len = fileno(f); |
964 | + if (len > 0) |
965 | + fchmod(len, S_IRUSR|S_IWUSR); |
966 | + } |
967 | + } |
968 | + if (f) { |
969 | + int i; |
970 | + ncInstance * instance; |
971 | + char myName[CHAR_BUFFER_SIZE]; |
972 | + |
973 | + fprintf(f, "version: %s\n", EUCA_VERSION); |
974 | + fprintf(f, "timestamp: %ld\n", time(NULL)); |
975 | + if (gethostname(myName, CHAR_BUFFER_SIZE) == 0) |
976 | + fprintf(f, "node: %s\n", myName); |
977 | + fprintf(f, "hypervisor: %s\n", nc_state.H->name); |
978 | + fprintf(f, "network: %s\n", nc_state.vnetconfig->mode); |
979 | + |
980 | + used_disk = used_mem = used_cores = 0; |
981 | + for (i=0; i < (*outInstsLen); i++) { |
982 | + instance = (*outInsts)[i]; |
983 | + used_disk += instance->params.disk; |
984 | + used_mem += instance->params.mem; |
985 | + used_cores += instance->params.cores; |
986 | + } |
987 | + |
988 | + fprintf(f, "memory (max/avail/used) MB: %lld/%lld/%lld\n", nc_state.mem_max, nc_state.mem_max - used_mem, used_mem); |
989 | + fprintf(f, "disk (max/avail/used) GB: %lld/%lld/%lld\n", nc_state.disk_max, nc_state.disk_max - used_disk, used_disk); |
990 | + fprintf(f, "cores (max/avail/used): %lld/%lld/%lld\n", nc_state.cores_max, nc_state.cores_max - used_cores, used_cores); |
991 | + |
992 | + for (i=0; i < (*outInstsLen); i++) { |
993 | + instance = (*outInsts)[i]; |
994 | + fprintf(f, "id: %s", instance->instanceId); |
995 | + fprintf(f, " userId: %s", instance->userId); |
996 | + fprintf(f, " state: %s", instance->stateName); |
997 | + fprintf(f, " mem: %d", instance->params.mem); |
998 | + fprintf(f, " disk: %d", instance->params.disk); |
999 | + fprintf(f, " cores: %d", instance->params.cores); |
1000 | + fprintf(f, " private: %s", instance->ncnet.privateIp); |
1001 | + fprintf(f, " public: %s\n", instance->ncnet.publicIp); |
1002 | + } |
1003 | + fclose(f); |
1004 | + } |
1005 | + } |
1006 | + free(file_name); |
1007 | + |
1008 | + return ret; |
1009 | +} |
1010 | + |
1011 | +int doPowerDown(ncMetadata *meta) { |
1012 | + int ret; |
1013 | + |
1014 | + if (init()) |
1015 | + return 1; |
1016 | + |
1017 | + logprintfl(EUCADEBUG, "doPowerDown() invoked\n"); |
1018 | + |
1019 | + if (nc_state.H->doPowerDown) |
1020 | + ret = nc_state.H->doPowerDown(&nc_state, meta); |
1021 | + else |
1022 | + ret = nc_state.D->doPowerDown(&nc_state, meta); |
1023 | + |
1024 | + return ret; |
1025 | +} |
1026 | + |
1027 | +int doRunInstance (ncMetadata *meta, char *instanceId, char *reservationId, virtualMachine *params, char *imageId, char *imageURL, char *kernelId, char *kernelURL, char *ramdiskId, char *ramdiskURL, char *keyName, netConfig *netparams, char *userData, char *launchIndex, char **groupNames, int groupNamesSize, ncInstance **outInst) |
1028 | +{ |
1029 | + int ret; |
1030 | + |
1031 | + if (init()) |
1032 | + return 1; |
1033 | + |
1034 | + logprintfl (EUCAINFO, "doRunInstance() invoked (id=%s cores=%d disk=%d memory=%d)\n", instanceId, params->cores, params->disk, params->mem); |
1035 | + logprintfl (EUCAINFO, " image=%s at %s\n", imageId, imageURL); |
1036 | + if (kernelId && kernelURL) |
1037 | + logprintfl (EUCAINFO, " krnel=%s at %s\n", kernelId, kernelURL); |
1038 | + if (ramdiskId && ramdiskURL) |
1039 | + logprintfl (EUCAINFO, " rmdsk=%s at %s\n", ramdiskId, ramdiskURL); |
1040 | + logprintfl (EUCAINFO, " vlan=%d priMAC=%s privIp=%s\n", netparams->vlan, netparams->privateMac, netparams->privateIp); |
1041 | + |
1042 | + int i; |
1043 | + for (i=0; i<EUCA_MAX_DEVMAPS; i++) { |
1044 | + deviceMapping * dm = &(params->deviceMapping[i]); |
1045 | + if (strlen(dm->deviceName)>0) { |
1046 | + logprintfl (EUCAINFO, " device mapping: %s=%s size=%d format=%s\n", dm->deviceName, dm->virtualName, dm->size, dm->format); |
1047 | + } |
1048 | + } |
1049 | + |
1050 | + if (nc_state.H->doRunInstance) |
1051 | + ret = nc_state.H->doRunInstance (&nc_state, meta, instanceId, reservationId, params, imageId, imageURL, kernelId, kernelURL, ramdiskId, ramdiskURL, keyName, netparams, userData, launchIndex, groupNames, groupNamesSize, outInst); |
1052 | + else |
1053 | + ret = nc_state.D->doRunInstance (&nc_state, meta, instanceId, reservationId, params, imageId, imageURL, kernelId, kernelURL, ramdiskId, ramdiskURL, keyName, netparams, userData, launchIndex, groupNames, groupNamesSize, outInst); |
1054 | + |
1055 | + return ret; |
1056 | +} |
1057 | + |
1058 | +int doTerminateInstance (ncMetadata *meta, char *instanceId, int *shutdownState, int *previousState) |
1059 | +{ |
1060 | + int ret; |
1061 | + |
1062 | + if (init()) |
1063 | + return 1; |
1064 | + |
1065 | + logprintfl (EUCAINFO, "doTerminateInstance() invoked (id=%s)\n", instanceId); |
1066 | + |
1067 | + if (nc_state.H->doTerminateInstance) |
1068 | + ret = nc_state.H->doTerminateInstance(&nc_state, meta, instanceId, shutdownState, previousState); |
1069 | + else |
1070 | + ret = nc_state.D->doTerminateInstance(&nc_state, meta, instanceId, shutdownState, previousState); |
1071 | + |
1072 | + return ret; |
1073 | +} |
1074 | + |
1075 | +int doRebootInstance (ncMetadata *meta, char *instanceId) |
1076 | +{ |
1077 | + int ret; |
1078 | + |
1079 | + if (init()) |
1080 | + return 1; |
1081 | + |
1082 | + logprintfl(EUCAINFO, "doRebootInstance() invoked (id=%s)\n", instanceId); |
1083 | + |
1084 | + if (nc_state.H->doRebootInstance) |
1085 | + ret = nc_state.H->doRebootInstance (&nc_state, meta, instanceId); |
1086 | + else |
1087 | + ret = nc_state.D->doRebootInstance (&nc_state, meta, instanceId); |
1088 | + |
1089 | + return ret; |
1090 | +} |
1091 | + |
1092 | +int doGetConsoleOutput (ncMetadata *meta, char *instanceId, char **consoleOutput) |
1093 | +{ |
1094 | + int ret; |
1095 | + |
1096 | + if (init()) |
1097 | + return 1; |
1098 | + |
1099 | + logprintfl (EUCAINFO, "doGetConsoleOutput() invoked (id=%s)\n", instanceId); |
1100 | + |
1101 | + if (nc_state.H->doGetConsoleOutput) |
1102 | + ret = nc_state.H->doGetConsoleOutput (&nc_state, meta, instanceId, consoleOutput); |
1103 | + else |
1104 | + ret = nc_state.D->doGetConsoleOutput (&nc_state, meta, instanceId, consoleOutput); |
1105 | + |
1106 | + return ret; |
1107 | +} |
1108 | + |
1109 | +int doDescribeResource (ncMetadata *meta, char *resourceType, ncResource **outRes) |
1110 | +{ |
1111 | + int ret; |
1112 | + |
1113 | + if (init()) |
1114 | + return 1; |
1115 | + |
1116 | + logprintfl(EUCADEBUG, "doDescribeResource() invoked\n"); |
1117 | + |
1118 | + if (nc_state.H->doDescribeResource) |
1119 | + ret = nc_state.H->doDescribeResource (&nc_state, meta, resourceType, outRes); |
1120 | + else |
1121 | + ret = nc_state.D->doDescribeResource (&nc_state, meta, resourceType, outRes); |
1122 | + |
1123 | + return ret; |
1124 | +} |
1125 | + |
1126 | +int |
1127 | +doStartNetwork ( ncMetadata *ccMeta, |
1128 | + char **remoteHosts, |
1129 | + int remoteHostsLen, |
1130 | + int port, |
1131 | + int vlan) |
1132 | +{ |
1133 | + int ret; |
1134 | + |
1135 | + if (init()) |
1136 | + return 1; |
1137 | + |
1138 | + logprintfl(EUCADEBUG, "doStartNetwork() invoked\n"); |
1139 | + |
1140 | + if (nc_state.H->doStartNetwork) |
1141 | + ret = nc_state.H->doStartNetwork (&nc_state, ccMeta, remoteHosts, remoteHostsLen, port, vlan); |
1142 | + else |
1143 | + ret = nc_state.D->doStartNetwork (&nc_state, ccMeta, remoteHosts, remoteHostsLen, port, vlan); |
1144 | + |
1145 | + return ret; |
1146 | +} |
1147 | + |
1148 | +int doAttachVolume (ncMetadata *meta, char *instanceId, char *volumeId, char *remoteDev, char *localDev) |
1149 | +{ |
1150 | + int ret; |
1151 | + |
1152 | + if (init()) |
1153 | + return 1; |
1154 | + |
1155 | + logprintfl (EUCAINFO, "doAttachVolume() invoked (id=%s vol=%s remote=%s local=%s)\n", instanceId, volumeId, remoteDev, localDev); |
1156 | + |
1157 | + if (nc_state.H->doAttachVolume) |
1158 | + ret = nc_state.H->doAttachVolume(&nc_state, meta, instanceId, volumeId, remoteDev, localDev); |
1159 | + else |
1160 | + ret = nc_state.D->doAttachVolume(&nc_state, meta, instanceId, volumeId, remoteDev, localDev); |
1161 | + |
1162 | + return ret; |
1163 | +} |
1164 | + |
1165 | +int doDetachVolume (ncMetadata *meta, char *instanceId, char *volumeId, char *remoteDev, char *localDev, int force) |
1166 | +{ |
1167 | + int ret; |
1168 | + |
1169 | + if (init()) |
1170 | + return 1; |
1171 | + |
1172 | + logprintfl (EUCAINFO, "doDetachVolume() invoked (id=%s vol=%s remote=%s local=%s force=%d)\n", instanceId, volumeId, remoteDev, localDev, force); |
1173 | + |
1174 | + if (nc_state.H->doDetachVolume) |
1175 | + ret = nc_state.H->doDetachVolume (&nc_state, meta, instanceId, volumeId, remoteDev, localDev, force); |
1176 | + else |
1177 | + ret = nc_state.D->doDetachVolume (&nc_state, meta, instanceId, volumeId, remoteDev, localDev, force); |
1178 | + |
1179 | + return ret; |
1180 | +} |
1181 | + |
1182 | +int check_iscsi(char* dev_string) { |
1183 | + if(strchr(dev_string, ',') == NULL) |
1184 | + return 0; |
1185 | + return 1; |
1186 | +} |
1187 | + |
1188 | +void parse_target(char *dev_string) { |
1189 | + char *delimiter = ","; |
1190 | + char *brk, *part; |
1191 | + char dev_name[256]; |
1192 | + snprintf(dev_name, 256, "%s", dev_string); |
1193 | + |
1194 | + for (part = strtok_r(dev_name, delimiter, &brk); part != NULL; part = strtok_r(NULL, delimiter, &brk)) { |
1195 | + } |
1196 | +} |
1197 | + |
1198 | +char* connect_iscsi_target(const char *storage_cmd_path, char *dev_string) { |
1199 | + char buf [MAX_PATH]; |
1200 | + char *retval; |
1201 | + |
1202 | + snprintf (buf, MAX_PATH, "%s %s", storage_cmd_path, dev_string); |
1203 | + logprintfl (EUCAINFO, "connect_iscsi_target invoked (dev_string=%s)\n", dev_string); |
1204 | + if ((retval = system_output(buf)) == NULL) { |
1205 | + logprintfl (EUCAERROR, "ERROR: connect_iscsi_target failed\n"); |
1206 | + } else { |
1207 | + logprintfl (EUCAINFO, "Attached device: %s\n", retval); |
1208 | + } |
1209 | + return retval; |
1210 | +} |
1211 | + |
1212 | +int disconnect_iscsi_target(const char *storage_cmd_path, char *dev_string) { |
1213 | + logprintfl (EUCAINFO, "disconnect_iscsi_target invoked (dev_string=%s)\n", dev_string); |
1214 | + if (vrun("%s %s", storage_cmd_path, dev_string) != 0) { |
1215 | + logprintfl (EUCAERROR, "ERROR: disconnect_iscsi_target failed\n"); |
1216 | + return -1; |
1217 | + } |
1218 | + return 0; |
1219 | +} |
1220 | + |
1221 | +char* get_iscsi_target(const char *storage_cmd_path, char *dev_string) { |
1222 | + char buf [MAX_PATH]; |
1223 | + char *retval; |
1224 | + |
1225 | + snprintf (buf, MAX_PATH, "%s %s", storage_cmd_path, dev_string); |
1226 | + logprintfl (EUCAINFO, "get_iscsi_target invoked (dev_string=%s)\n", dev_string); |
1227 | + if ((retval = system_output(buf)) == NULL) { |
1228 | + logprintfl (EUCAERROR, "ERROR: get_iscsi_target failed\n"); |
1229 | + } else { |
1230 | + logprintfl (EUCAINFO, "Device: %s\n", retval); |
1231 | + } |
1232 | + return retval; |
1233 | +} |
1234 | + |
1235 | |
1236 | === added directory '.pc/22-uec-multiboot-kvm.patch/tools' |
1237 | === added file '.pc/22-uec-multiboot-kvm.patch/tools/Makefile' |
1238 | --- .pc/22-uec-multiboot-kvm.patch/tools/Makefile 1970-01-01 00:00:00 +0000 |
1239 | +++ .pc/22-uec-multiboot-kvm.patch/tools/Makefile 2010-07-30 21:11:15 +0000 |
1240 | @@ -0,0 +1,71 @@ |
1241 | +# Makefile for eucalyptus/tools |
1242 | +# |
1243 | +# |
1244 | + |
1245 | +include ../Makedefs |
1246 | + |
1247 | +all: |
1248 | + |
1249 | +build: all |
1250 | + |
1251 | +deploy: |
1252 | + |
1253 | +clean: |
1254 | + $(RM) -f *~ *.o |
1255 | + |
1256 | +distclean: |
1257 | + @echo "removing generated files scripts ..." |
1258 | + @rm -rf eucalyptus eucalyptus-cloud eucalyptus-walrus eucalyptus-sc |
1259 | + |
1260 | +install: build |
1261 | + @if test -e /etc/init.d/eucalyptus ; then \ |
1262 | + mv /etc/init.d/eucalyptus /etc/init.d/eucalyptus.old ; \ |
1263 | + echo "Moving away old init.d script"; fi |
1264 | + @if test -e $(DESTDIR)$(etcdir)/init.d/eucalyptus ; then \ |
1265 | + mv $(DESTDIR)$(etcdir)/init.d/eucalyptus $(DESTDIR)$(etcdir)/init.d/eucalyptus.old ; fi |
1266 | + @$(INSTALL) -m 755 eucalyptus-cloud $(DESTDIR)$(etcdir)/init.d |
1267 | + @$(INSTALL) -m 755 eucalyptus-nc $(DESTDIR)$(etcdir)/init.d |
1268 | + @$(INSTALL) -m 755 eucalyptus-cc $(DESTDIR)$(etcdir)/init.d |
1269 | + @$(INSTALL) -m 644 httpd.conf $(DESTDIR)$(etcdir)/eucalyptus |
1270 | + @if test -e $(DESTDIR)$(etcdir)/eucalyptus/eucalyptus.conf ; then \ |
1271 | + cp $(DESTDIR)$(etcdir)/eucalyptus/eucalyptus.conf $(DESTDIR)$(etcdir)/eucalyptus/eucalyptus.conf.old ; fi |
1272 | + @$(INSTALL) -m 644 eucalyptus.conf $(DESTDIR)$(etcdir)/eucalyptus |
1273 | + @$(INSTALL) -m 644 vtunall.conf.template $(DESTDIR)$(etcdir)/eucalyptus |
1274 | + @$(INSTALL) -m 755 add_key.pl $(DESTDIR)$(datarootdir)/eucalyptus |
1275 | + @$(INSTALL) -m 755 gen_libvirt_xml $(DESTDIR)$(datarootdir)/eucalyptus |
1276 | + @$(INSTALL) -m 755 gen_kvm_libvirt_xml $(DESTDIR)$(datarootdir)/eucalyptus |
1277 | + @$(INSTALL) -m 755 detach.pl $(DESTDIR)$(datarootdir)/eucalyptus |
1278 | + @$(INSTALL) -m 755 partition2disk $(DESTDIR)$(datarootdir)/eucalyptus |
1279 | + @$(INSTALL) -m 755 get_xen_info $(DESTDIR)$(datarootdir)/eucalyptus/get_xen_info |
1280 | + @$(INSTALL) -m 755 get_sys_info $(DESTDIR)$(datarootdir)/eucalyptus/get_sys_info |
1281 | + @$(INSTALL) -m 755 euca_ipt $(DESTDIR)$(datarootdir)/eucalyptus |
1282 | + @$(INSTALL) -m 755 euca_upgrade $(DESTDIR)$(datarootdir)/eucalyptus |
1283 | + @$(INSTALL) -m 755 populate_arp.pl $(DESTDIR)$(datarootdir)/eucalyptus |
1284 | + @$(INSTALL) -m 755 euca_conf $(DESTDIR)$(sbindir) |
1285 | + -$(INSTALL) -m 755 euca_conf.complete $(DESTDIR)/etc/bash_completion.d/euca_conf |
1286 | + @$(INSTALL) -m 755 euca_sync_key $(DESTDIR)$(sbindir) |
1287 | + @$(INSTALL) -m 755 connect_iscsitarget.pl $(DESTDIR)$(datarootdir)/eucalyptus |
1288 | + @$(INSTALL) -m 755 disconnect_iscsitarget.pl $(DESTDIR)$(datarootdir)/eucalyptus |
1289 | + @$(INSTALL) -m 755 get_iscsitarget.pl $(DESTDIR)$(datarootdir)/eucalyptus |
1290 | + |
1291 | +uninstall: |
1292 | + @$(RM) -f $(DESTDIR)$(etcdir)/init.d/eucalyptus-cloud |
1293 | + @$(RM) -f $(DESTDIR)$(etcdir)/init.d/eucalyptus-nc |
1294 | + @$(RM) -f $(DESTDIR)$(etcdir)/init.d/eucalyptus-cc |
1295 | + @$(RM) -f $(DESTDIR)$(etcdir)/eucalyptus/httpd* |
1296 | + @$(RM) -f $(DESTDIR)$(etcdir)/eucalyptus/eucalyptus.conf |
1297 | + @$(RM) -f $(DESTDIR)$(etcdir)/eucalyptus/vtunall.conf.template |
1298 | + @$(RM) -f $(DESTDIR)$(datarootdir)/eucalyptus/add_key.pl |
1299 | + @$(RM) -f $(DESTDIR)$(datarootdir)/eucalyptus/gen_libvirt_xml |
1300 | + @$(RM) -f $(DESTDIR)$(datarootdir)/eucalyptus/gen_kvm_libvirt_xml |
1301 | + @$(RM) -f $(DESTDIR)$(datarootdir)/eucalyptus/detach.pl |
1302 | + @$(RM) -f $(DESTDIR)$(datarootdir)/eucalyptus/partition2disk |
1303 | + @$(RM) -f $(DESTDIR)$(datarootdir)/eucalyptus/get_xen_info |
1304 | + @$(RM) -f $(DESTDIR)$(datarootdir)/eucalyptus/get_sys_info |
1305 | + @$(RM) -f $(DESTDIR)$(datarootdir)/eucalyptus/euca_ipt |
1306 | + @$(RM) -f $(DESTDIR)$(datarootdir)/eucalyptus/euca_upgrade |
1307 | + @$(RM) -f $(DESTDIR)$(datarootdir)/eucalyptus/populate_arp.pl |
1308 | + @$(RM) -f $(DESTDIR)$(sbindir)/euca_conf |
1309 | + @$(RM) -f $(DESTDIR)/etc/bash_completion.d/euca_conf |
1310 | + @$(RM) -f $(DESTDIR)$(sbindir)/euca_sync_key |
1311 | + |
1312 | |
1313 | === added file '.pc/22-uec-multiboot-kvm.patch/tools/gen_kvm_libvirt_xml' |
1314 | --- .pc/22-uec-multiboot-kvm.patch/tools/gen_kvm_libvirt_xml 1970-01-01 00:00:00 +0000 |
1315 | +++ .pc/22-uec-multiboot-kvm.patch/tools/gen_kvm_libvirt_xml 2010-07-30 21:11:15 +0000 |
1316 | @@ -0,0 +1,165 @@ |
1317 | +#!/usr/bin/perl |
1318 | +#Copyright (c) 2009 Eucalyptus Systems, Inc. |
1319 | +# |
1320 | +#This program is free software: you can redistribute it and/or modify |
1321 | +#it under the terms of the GNU General Public License as published by |
1322 | +#the Free Software Foundation, only version 3 of the License. |
1323 | +# |
1324 | +#This file is distributed in the hope that it will be useful, but WITHOUT |
1325 | +#ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
1326 | +#FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
1327 | +#for more details. |
1328 | +# |
1329 | +#You should have received a copy of the GNU General Public License along |
1330 | +#with this program. If not, see <http://www.gnu.org/licenses/>. |
1331 | +# |
1332 | +#Please contact Eucalyptus Systems, Inc., 130 Castilian |
1333 | +#Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/> |
1334 | +#if you need additional information or have any questions. |
1335 | +# |
1336 | +#This file may incorporate work covered under the following copyright and |
1337 | +#permission notice: |
1338 | +# |
1339 | +# Software License Agreement (BSD License) |
1340 | +# |
1341 | +# Copyright (c) 2008, Regents of the University of California |
1342 | +# |
1343 | +# |
1344 | +# Redistribution and use of this software in source and binary forms, with |
1345 | +# or without modification, are permitted provided that the following |
1346 | +# conditions are met: |
1347 | +# |
1348 | +# Redistributions of source code must retain the above copyright notice, |
1349 | +# this list of conditions and the following disclaimer. |
1350 | +# |
1351 | +# Redistributions in binary form must reproduce the above copyright |
1352 | +# notice, this list of conditions and the following disclaimer in the |
1353 | +# documentation and/or other materials provided with the distribution. |
1354 | +# |
1355 | +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
1356 | +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
1357 | +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
1358 | +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER |
1359 | +# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
1360 | +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
1361 | +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
1362 | +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
1363 | +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
1364 | +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
1365 | +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF |
1366 | +# THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE |
1367 | +# LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS |
1368 | +# SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING |
1369 | +# IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA |
1370 | +# BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN |
1371 | +# THE REGENTS’ DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT |
1372 | +# OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR |
1373 | +# WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH |
1374 | +# ANY SUCH LICENSES OR RIGHTS. |
1375 | +# |
1376 | + |
1377 | +# |
1378 | +# this generates an XML template for libvirt domain specification, |
1379 | +# which is tailored to an instance by the node controller |
1380 | + |
1381 | +use diagnostics; |
1382 | +use warnings; |
1383 | +use sigtrap; |
1384 | +use strict; |
1385 | +use English; # for descriptive predefined var names |
1386 | +use Data::Dumper; # for debugging: print Dumper($var) |
1387 | +use Getopt::Long; |
1388 | +use FindBin; |
1389 | +$OUTPUT_AUTOFLUSH = 1; # no output buffering |
1390 | + |
1391 | +our $use_ramdisk = 0; |
1392 | +our $local_kvm=""; |
1393 | +our $use_virtio_net = 0; |
1394 | +our $use_virtio_root = 0; |
1395 | + |
1396 | +if ( -x "/usr/bin/kvm" ) { |
1397 | + $local_kvm="/usr/bin/kvm"; |
1398 | +} elsif ( -x "/usr/bin/qemu-kvm" ) { |
1399 | + $local_kvm="/usr/bin/qemu-kvm"; |
1400 | +} else { |
1401 | + $local_kvm="kvm"; |
1402 | +} |
1403 | + |
1404 | +# deal with command-line parameters |
1405 | +GetOptions('ramdisk' => sub { $use_ramdisk = 1; }, |
1406 | + 'ephemeral' => sub { }, # option ignored |
1407 | + 'virtionet' => sub { $use_virtio_net = 1; }, |
1408 | + 'virtioroot' => sub { $use_virtio_root = 1; }, |
1409 | + ) or exit (1); |
1410 | + |
1411 | +print <<EOF; |
1412 | +<domain type='kvm'> |
1413 | + <name>NAME</name> |
1414 | + <os> |
1415 | + <type>hvm</type> |
1416 | + <kernel>BASEPATH/kernel</kernel> |
1417 | +EOF |
1418 | + |
1419 | +if ( $use_ramdisk ) { |
1420 | + print " <initrd>BASEPATH/ramdisk</initrd>\n"; |
1421 | +} |
1422 | + |
1423 | +if ( $use_virtio_root ) { |
1424 | + print " <cmdline>root=/dev/vda1 console=ttyS0</cmdline>\n" |
1425 | +} else { |
1426 | + print " <cmdline>root=/dev/sda1 console=ttyS0</cmdline>\n" |
1427 | +} |
1428 | + |
1429 | +print <<EOF; |
1430 | + </os> |
1431 | + <features> |
1432 | + <acpi/> |
1433 | + </features> |
1434 | + <memory>MEMORY</memory> |
1435 | + <vcpu>VCPUS</vcpu> |
1436 | + <devices> |
1437 | + <emulator>$local_kvm</emulator> |
1438 | +EOF |
1439 | + |
1440 | +if ( $use_virtio_root ) { |
1441 | + print <<EOF; |
1442 | + <disk type='file' device='disk'> |
1443 | + <source file='BASEPATH/disk'/> |
1444 | + <target dev='vda' bus='virtio'/> |
1445 | + </disk> |
1446 | +EOF |
1447 | +} else { |
1448 | + print <<EOF; |
1449 | + <disk type='file'> |
1450 | + <source file='BASEPATH/disk'/> |
1451 | + <target dev='sda'/> |
1452 | + </disk> |
1453 | +EOF |
1454 | +} |
1455 | + |
1456 | +if ( $use_virtio_net ) { |
1457 | + print <<EOF; |
1458 | + <interface type='bridge'> |
1459 | + <source bridge='BRIDGEDEV'/> |
1460 | + <mac address='PRIVMACADDR'/> |
1461 | + <model type='virtio'/> |
1462 | + </interface> |
1463 | +EOF |
1464 | +} else { |
1465 | + print <<EOF; |
1466 | + <interface type='bridge'> |
1467 | + <source bridge='BRIDGEDEV'/> |
1468 | + <mac address='PRIVMACADDR'/> |
1469 | + <model type='e1000'/> |
1470 | + </interface> |
1471 | +EOF |
1472 | +} |
1473 | + |
1474 | +print <<EOF; |
1475 | + <serial type="file"> |
1476 | + <source path='BASEPATH/console.log'/> |
1477 | + <target port='1'/> |
1478 | + </serial> |
1479 | + </devices> |
1480 | +</domain> |
1481 | +EOF |
1482 | |
1483 | === added file '.pc/22-uec-multiboot-kvm.patch/tools/mk-mb-loader' |
1484 | === added directory '.pc/22-uec-multiboot-kvm.patch/util' |
1485 | === added file '.pc/22-uec-multiboot-kvm.patch/util/wrappers.conf' |
1486 | --- .pc/22-uec-multiboot-kvm.patch/util/wrappers.conf 1970-01-01 00:00:00 +0000 |
1487 | +++ .pc/22-uec-multiboot-kvm.patch/util/wrappers.conf 2010-07-30 21:11:15 +0000 |
1488 | @@ -0,0 +1,51 @@ |
1489 | +# wrapper-name fully-qualified-path uid-or-capability-to-use |
1490 | +# |
1491 | +# Networking |
1492 | +ip /sbin/ip 0 #cap_net_admin |
1493 | +iptables /sbin/iptables 0 #cap_net_admin |
1494 | +iptables-save /sbin/iptables-save 0 #cap_net_admin |
1495 | +iptables-restore /sbin/iptables-restore 0 #cap_net_admin |
1496 | +euca_ipt /usr/share/eucalyptus/euca_ipt 0 #cap_net_admin # where does this write its tempfiles? |
1497 | +dhcpd3 /usr/sbin/dhcpd3 0 #cap_net_admin |
1498 | +vtund /usr/sbin/vtund 0 #cap_net_admin |
1499 | +vconfig /sbin/vconfig 0 #cap_net_admin |
1500 | +brctl /usr/sbin/brctl 0 #cap_net_admin |
1501 | +populate_arp.pl /usr/share/eucalyptus/populate_arp.pl 0 |
1502 | +# Helpers |
1503 | +vblade /usr/sbin/vblade 0 |
1504 | +get_sys_info /usr/share/eucalyptus/get_sys_info 0 |
1505 | +get_xen_info /usr/share/eucalyptus/get_xen_info 0 |
1506 | +add_key.pl /usr/share/eucalyptus/add_key.pl 0 |
1507 | +partition2disk /usr/share/eucalyptus/partition2disk 0 |
1508 | +gen_kvm_libvirt_xml /usr/share/eucalyptus/gen_kvm_libvirt_xml 0 |
1509 | +gen_libvirt_xml /usr/share/eucalyptus/gen_libvirt_xml 0 |
1510 | +detach.pl /usr/share/eucalyptus/detach.pl 0 |
1511 | +# Services |
1512 | +powernap /usr/sbin/powernap-now 0 |
1513 | +# LVM management |
1514 | +losetup /sbin/losetup 0 |
1515 | +lvm /sbin/lvm 0 |
1516 | +pvcreate /sbin/pvcreate 0 |
1517 | +vgcreate /sbin/vgcreate 0 |
1518 | +vgextend /sbin/vgextend 0 |
1519 | +lvremove /sbin/lvremove 0 |
1520 | +lvchange /sbin/lvchange 0 |
1521 | +lvcreate /sbin/lvcreate 0 |
1522 | +vgremove /sbin/vgremove 0 |
1523 | +pvremove /sbin/pvremove 0 |
1524 | +vgreduce /sbin/vgreduce 0 |
1525 | +dmsetup /sbin/dmsetup 0 |
1526 | +kill /bin/kill 0 |
1527 | +id /usr/bin/id 0 |
1528 | +ietadm /usr/sbin/ietadm 0 |
1529 | +# redirected wrappers |
1530 | +modprobe /usr/share/eucalyptus/modprobe-aoe 0 #cap_sys_module |
1531 | +dd /usr/share/eucalyptus/dd-lv 0 |
1532 | +# need to write wrapper |
1533 | +chgrp /usr/share/eucalyptus/chgrp-dhcpd 0 |
1534 | +chmod /usr/share/eucalyptus/chmod-dhcpd 0 |
1535 | +# These do not need root wrapping |
1536 | +cat /bin/cat |
1537 | +powerwake /usr/bin/powerwake |
1538 | +virsh /usr/bin/virsh |
1539 | +which /usr/bin/which |
1540 | |
1541 | === modified file '.pc/applied-patches' |
1542 | --- .pc/applied-patches 2010-07-21 17:27:10 +0000 |
1543 | +++ .pc/applied-patches 2010-07-30 21:11:15 +0000 |
1544 | @@ -14,3 +14,4 @@ |
1545 | 18-priv_security.patch |
1546 | 20-brute-force-webui.patch |
1547 | 21-eucalyptus-1.7-with-gwt-1.6.4.patch |
1548 | +22-uec-multiboot-kvm.patch |
1549 | |
1550 | === modified file 'debian/changelog' |
1551 | --- debian/changelog 2010-07-21 17:27:10 +0000 |
1552 | +++ debian/changelog 2010-07-30 21:11:15 +0000 |
1553 | @@ -1,3 +1,9 @@ |
1554 | +eucalyptus (2.0~bzr1211-0ubuntu2) UNRELEASED; urgency=low |
1555 | + |
1556 | + * add support for booting multiboot images from a floppy (LP: #611144) |
1557 | + |
1558 | + -- Scott Moser <smoser@ubuntu.com> Thu, 29 Jul 2010 02:31:00 -0400 |
1559 | + |
1560 | eucalyptus (2.0~bzr1211-0ubuntu1) maverick; urgency=low |
1561 | |
1562 | * New major upstream version merge, 2.0 (r1211). |
1563 | |
1564 | === modified file 'debian/control' |
1565 | --- debian/control 2010-07-21 17:27:10 +0000 |
1566 | +++ debian/control 2010-07-30 21:11:15 +0000 |
1567 | @@ -263,7 +263,10 @@ |
1568 | libapache2-mod-axis2c, |
1569 | eucalyptus-gl, |
1570 | adduser, |
1571 | - iptables |
1572 | + iptables, |
1573 | + xorriso, |
1574 | + grub-common, |
1575 | + grub-pc |
1576 | Suggests: aoetools |
1577 | Recommends: |
1578 | qemu-kvm, |
1579 | |
1580 | === modified file 'debian/eucalyptus-nc.install' |
1581 | --- debian/eucalyptus-nc.install 2009-12-17 18:22:02 +0000 |
1582 | +++ debian/eucalyptus-nc.install 2010-07-30 21:11:15 +0000 |
1583 | @@ -5,6 +5,7 @@ |
1584 | /usr/share/eucalyptus/get_xen_info |
1585 | /usr/share/eucalyptus/get_sys_info |
1586 | /usr/share/eucalyptus/partition2disk |
1587 | +/usr/share/eucalyptus/mk-mb-loader |
1588 | /usr/sbin/euca_test_nc |
1589 | /usr/lib/axis2/services/EucalyptusNC |
1590 | debian/30-eucalyptus-nc.conf etc/sysctl.d |
1591 | |
1592 | === added file 'debian/patches/22-uec-multiboot-kvm.patch' |
1593 | --- debian/patches/22-uec-multiboot-kvm.patch 1970-01-01 00:00:00 +0000 |
1594 | +++ debian/patches/22-uec-multiboot-kvm.patch 2010-07-30 21:11:15 +0000 |
1595 | @@ -0,0 +1,292 @@ |
1596 | +Description: add support for booting a multiboot image from a floppy |
1597 | + This adds a tool 'mk-mb-loader' which takes a multiboot compliant image |
1598 | + and puts it onto a floppy disk image and loads it. |
1599 | + . |
1600 | + It also contains modifications to gen_kvm_libvirt_xml that |
1601 | + a.) make mk-mb-loader run |
1602 | + b.) modify libvirt xml output to add a floppy disk and boot |
1603 | + off it rather than booting via '<kernel>' |
1604 | + . |
1605 | + The hack to boot off of a floppy is required because when a multiboot |
1606 | + image is loaded by 'kvm -kernel "mb.img"', it will not have access to |
1607 | + scsi disks. That means that if a scsi disk is the root block device |
1608 | + that the multiboot image will not see any disks. |
1609 | + . |
1610 | + The solution is to boot via floppy instead. The mk-mb-image creates |
1611 | + a floppy disk that loads the user provided multiboot image. |
1612 | + . |
1613 | + In the future, this patch can be dropped if either of the following occur: |
1614 | + a.) scsi root disk support is abandoned |
1615 | + b.) seabios gains native support for scsi disks, such that |
1616 | + 'kvm -kernel <mb.img' has access to scsi disks as it has access to |
1617 | + ide or virtio disks in seabios 0.6.0-0ubuntu1. |
1618 | + . |
1619 | + That would provide a much more clean solution of simply booting with |
1620 | + '-kernel' whatever the user provided. |
1621 | +Author: Scott Moser <scott.moser@canonical.com> |
1622 | +Last-Update: 2010-07-28 |
1623 | +Bug: https://bugs.launchpad.net/eucalyptus/+bug/611144 |
1624 | +Index: maverick/node/handlers.c |
1625 | +=================================================================== |
1626 | +--- maverick.orig/node/handlers.c 2010-07-29 02:31:52.278870002 -0400 |
1627 | ++++ maverick/node/handlers.c 2010-07-29 02:31:54.698870002 -0400 |
1628 | +@@ -380,6 +380,7 @@ |
1629 | + char **xml) |
1630 | + { |
1631 | + char buf [MAX_PATH]; |
1632 | ++ char patharg [MAX_PATH]; |
1633 | + |
1634 | + snprintf(buf, MAX_PATH, "%s", gen_libvirt_cmd_path); |
1635 | + if (strnlen(ramdiskId, CHAR_BUFFER_SIZE)) { |
1636 | +@@ -395,6 +396,9 @@ |
1637 | + if (params->disk > 0) { /* TODO: get this info from scMakeImage */ |
1638 | + strncat (buf, " --ephemeral", MAX_PATH); |
1639 | + } |
1640 | ++ snprintf(buf+strnlen(buf,MAX_PATH), MAX_PATH-strnlen(buf,MAX_PATH), |
1641 | ++ " --basepath='%s'", disk_path); |
1642 | ++ |
1643 | + * xml = system_output (buf); |
1644 | + if ( ( * xml ) == NULL ) { |
1645 | + logprintfl (EUCAFATAL, "%s: %s\n", gen_libvirt_cmd_path, strerror (errno)); |
1646 | +Index: maverick/tools/gen_kvm_libvirt_xml |
1647 | +=================================================================== |
1648 | +--- maverick.orig/tools/gen_kvm_libvirt_xml 2010-07-29 02:31:52.238870002 -0400 |
1649 | ++++ maverick/tools/gen_kvm_libvirt_xml 2010-07-30 17:05:10.978870002 -0400 |
1650 | +@@ -76,6 +76,8 @@ |
1651 | + our $local_kvm=""; |
1652 | + our $use_virtio_net = 0; |
1653 | + our $use_virtio_root = 0; |
1654 | ++our $base_path = ""; |
1655 | ++our $multi_boot_floppy = 0; |
1656 | + |
1657 | + if ( -x "/usr/bin/kvm" ) { |
1658 | + $local_kvm="/usr/bin/kvm"; |
1659 | +@@ -90,24 +92,39 @@ |
1660 | + 'ephemeral' => sub { }, # option ignored |
1661 | + 'virtionet' => sub { $use_virtio_net = 1; }, |
1662 | + 'virtioroot' => sub { $use_virtio_root = 1; }, |
1663 | ++ 'basepath=s' => \$base_path, |
1664 | + ) or exit (1); |
1665 | + |
1666 | ++if ($base_path && &is_multiboot_img($base_path . "/kernel") && |
1667 | ++ ! $use_virtio_root ) { |
1668 | ++ $multi_boot_floppy = 1; |
1669 | ++} |
1670 | ++ |
1671 | + print <<EOF; |
1672 | + <domain type='kvm'> |
1673 | + <name>NAME</name> |
1674 | + <os> |
1675 | + <type>hvm</type> |
1676 | +- <kernel>BASEPATH/kernel</kernel> |
1677 | + EOF |
1678 | + |
1679 | +-if ( $use_ramdisk ) { |
1680 | +- print " <initrd>BASEPATH/ramdisk</initrd>\n"; |
1681 | +-} |
1682 | +- |
1683 | +-if ( $use_virtio_root ) { |
1684 | +- print " <cmdline>root=/dev/vda1 console=ttyS0</cmdline>\n" |
1685 | ++if ( $multi_boot_floppy ) { |
1686 | ++ my $mb_load_cmd = "/usr/share/eucalyptus/mk-mb-loader " . |
1687 | ++ "'" . $base_path . "/kernel' '" . $base_path . "/loader' 2>&1"; |
1688 | ++ my $mb_out = `$mb_load_cmd`; |
1689 | ++ if ( $? != 0 ) { print("failed to make loader\n${mb_out}\n"); exit(1); } |
1690 | ++ print " <boot dev='fd'/>\n"; |
1691 | ++ print " <boot dev='hd'/>\n"; |
1692 | + } else { |
1693 | +- print " <cmdline>root=/dev/sda1 console=ttyS0</cmdline>\n" |
1694 | ++ print " <kernel>BASEPATH/kernel</kernel>\n"; |
1695 | ++ if ( $use_ramdisk ) { |
1696 | ++ print " <initrd>BASEPATH/ramdisk</initrd>\n"; |
1697 | ++ } |
1698 | ++ |
1699 | ++ if ( $use_virtio_root ) { |
1700 | ++ print " <cmdline>root=/dev/vda1 console=ttyS0</cmdline>\n" |
1701 | ++ } else { |
1702 | ++ print " <cmdline>root=/dev/sda1 console=ttyS0</cmdline>\n" |
1703 | ++ } |
1704 | + } |
1705 | + |
1706 | + print <<EOF; |
1707 | +@@ -121,6 +138,15 @@ |
1708 | + <emulator>$local_kvm</emulator> |
1709 | + EOF |
1710 | + |
1711 | ++if ( $multi_boot_floppy ) { |
1712 | ++ print <<EOF |
1713 | ++ <disk type='file' device='floppy'> |
1714 | ++ <source file='BASEPATH/loader'/> |
1715 | ++ <target dev='fda' bus='fdc'/> |
1716 | ++ </disk> |
1717 | ++EOF |
1718 | ++} |
1719 | ++ |
1720 | + if ( $use_virtio_root ) { |
1721 | + print <<EOF; |
1722 | + <disk type='file' device='disk'> |
1723 | +@@ -163,3 +189,16 @@ |
1724 | + </devices> |
1725 | + </domain> |
1726 | + EOF |
1727 | ++ |
1728 | ++# this needs to be improved greatly, but the intent is |
1729 | ++# to determine if this is multiboot image or not. |
1730 | ++# grub-0.97 provide 'mbchk' that would have been great, that |
1731 | ++# is not available in grub2 |
1732 | ++sub is_multiboot_img |
1733 | ++{ |
1734 | ++ my $kpath=$_[0]; |
1735 | ++ if (! (-s $kpath)) { return(0); } |
1736 | ++ system("/usr/bin/file '" . $kpath . "' | grep -q 'Linux kernel'"); |
1737 | ++ if ($? == 0) { return(0); } |
1738 | ++ return(1) |
1739 | ++} |
1740 | +Index: maverick/util/wrappers.conf |
1741 | +=================================================================== |
1742 | +--- maverick.orig/util/wrappers.conf 2010-07-29 02:31:52.258870002 -0400 |
1743 | ++++ maverick/util/wrappers.conf 2010-07-29 02:31:54.698870002 -0400 |
1744 | +@@ -20,6 +20,7 @@ |
1745 | + gen_kvm_libvirt_xml /usr/share/eucalyptus/gen_kvm_libvirt_xml 0 |
1746 | + gen_libvirt_xml /usr/share/eucalyptus/gen_libvirt_xml 0 |
1747 | + detach.pl /usr/share/eucalyptus/detach.pl 0 |
1748 | ++mk-mb-loader /usr/share/eucalyptus/mk-mb-loader 0 |
1749 | + # Services |
1750 | + powernap /usr/sbin/powernap-now 0 |
1751 | + # LVM management |
1752 | +Index: maverick/tools/Makefile |
1753 | +=================================================================== |
1754 | +--- maverick.orig/tools/Makefile 2010-07-29 02:31:52.248870002 -0400 |
1755 | ++++ maverick/tools/Makefile 2010-07-29 02:31:54.698870002 -0400 |
1756 | +@@ -47,6 +47,7 @@ |
1757 | + @$(INSTALL) -m 755 connect_iscsitarget.pl $(DESTDIR)$(datarootdir)/eucalyptus |
1758 | + @$(INSTALL) -m 755 disconnect_iscsitarget.pl $(DESTDIR)$(datarootdir)/eucalyptus |
1759 | + @$(INSTALL) -m 755 get_iscsitarget.pl $(DESTDIR)$(datarootdir)/eucalyptus |
1760 | ++ @$(INSTALL) -m 755 mk-mb-loader $(DESTDIR)$(datarootdir)/eucalyptus |
1761 | + |
1762 | + uninstall: |
1763 | + @$(RM) -f $(DESTDIR)$(etcdir)/init.d/eucalyptus-cloud |
1764 | +@@ -68,4 +69,5 @@ |
1765 | + @$(RM) -f $(DESTDIR)$(sbindir)/euca_conf |
1766 | + @$(RM) -f $(DESTDIR)/etc/bash_completion.d/euca_conf |
1767 | + @$(RM) -f $(DESTDIR)$(sbindir)/euca_sync_key |
1768 | ++ @$(RM) -f $(DESTDIR)$(datarootdir)/eucalyptus/mk-mb-loader |
1769 | + |
1770 | +Index: maverick/tools/mk-mb-loader |
1771 | +=================================================================== |
1772 | +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 |
1773 | ++++ maverick/tools/mk-mb-loader 2010-07-29 02:31:54.698870002 -0400 |
1774 | +@@ -0,0 +1,113 @@ |
1775 | ++#!/bin/sh |
1776 | ++# vi: ts=4 noexpandtab |
1777 | ++# |
1778 | ++# Copyright (C) 2010 Canonical Ltd. |
1779 | ++# |
1780 | ++# Authors: Scott Moser <smoser@canonical.com> |
1781 | ++# |
1782 | ++# This program is free software: you can redistribute it and/or modify |
1783 | ++# it under the terms of the GNU General Public License as published by |
1784 | ++# the Free Software Foundation, version 3 of the License. |
1785 | ++# |
1786 | ++# This program is distributed in the hope that it will be useful, |
1787 | ++# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1788 | ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1789 | ++# GNU General Public License for more details. |
1790 | ++# |
1791 | ++# You should have received a copy of the GNU General Public License |
1792 | ++# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1793 | ++ |
1794 | ++TEMP_D="" |
1795 | ++ |
1796 | ++error() { echo "$@" 1>&2; } |
1797 | ++fail() { [ $# -eq 0 ] || error "$@"; exit 1; } |
1798 | ++Usage() { |
1799 | ++ cat <<EOF |
1800 | ++Usage: ${0##*/} loader.img output.img |
1801 | ++ Create a multiboot floppy image that will multiboot 'loader.img' |
1802 | ++ where loader.img is a multiboot complient loader |
1803 | ++ |
1804 | ++ The output.img file can then be booted with |
1805 | ++ kvm -fda output.img -boot a -drive ... |
1806 | ++ and will load 'loader.img' |
1807 | ++EOF |
1808 | ++} |
1809 | ++bad_Usage() { Usage 1>&2; fail "$@"; } |
1810 | ++cleanup() { |
1811 | ++ [ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}" |
1812 | ++} |
1813 | ++ |
1814 | ++getsize() { |
1815 | ++ local f="$1" size="" |
1816 | ++ size=$(ls -l "${f}" 2>/dev/null | awk '{print $5}') && |
1817 | ++ [ -n "${size}" ] && _RET=${size} && return 0 |
1818 | ++} |
1819 | ++checksize() { |
1820 | ++ getsize "$1" || return 1 |
1821 | ++ [ "${_RET}" "$2" "$3" ] |
1822 | ++} |
1823 | ++ |
1824 | ++mk_grub_rescue() { |
1825 | ++ local input=${1} output=${2} |
1826 | ++ local bdir="${TEMP_D}/bdir" |
1827 | ++ local err="${TEMP_D}/err" |
1828 | ++ local modules="configfile" |
1829 | ++ local modules="" |
1830 | ++ mkdir "${bdir}" && |
1831 | ++ mkdir -p "${bdir}/boot/grub" && |
1832 | ++ cp "${input}" "${bdir}/boot/grub/loader.img" && |
1833 | ++ cat > "${bdir}/boot/grub/grub.cfg" <<EOF |
1834 | ++multiboot /boot/grub/loader.img |
1835 | ++boot |
1836 | ++EOF |
1837 | ++ [ $? -eq 0 ] || return |
1838 | ++ grub-mkrescue --output="${output}" \ |
1839 | ++ ${modules:+"--modules=${modules}"} "${bdir}" > "${err}" 2>&1 || |
1840 | ++ { cat "${err}" 1>&2; return 1; } |
1841 | ++} |
1842 | ++ |
1843 | ++short_opts="h" |
1844 | ++long_opts="help" |
1845 | ++getopt_out=$(getopt --name "${0##*/}" \ |
1846 | ++ --options "${short_opts}" --long "${long_opts}" -- "$@") && |
1847 | ++ eval set -- "${getopt_out}" || |
1848 | ++ bad_Usage |
1849 | ++ |
1850 | ++mode="grub-rescue-floppy" |
1851 | ++while [ $# -ne 0 ]; do |
1852 | ++ cur=${1}; next=${2}; |
1853 | ++ case "$cur" in |
1854 | ++ -h|--help) Usage; exit 0;; |
1855 | ++ --) shift; break;; |
1856 | ++ esac |
1857 | ++ shift; |
1858 | ++done |
1859 | ++ |
1860 | ++[ $# -eq 2 ] || bad_Usage "must multiboot loader input and output file" |
1861 | ++ |
1862 | ++TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/.${0##*/}.XXXXXX") || |
1863 | ++ fail "failed to make tempd" |
1864 | ++trap cleanup EXIT |
1865 | ++ |
1866 | ++loader=${1} |
1867 | ++output=${2} |
1868 | ++ |
1869 | ++case "${mode}" in |
1870 | ++ grub-rescue-floppy) |
1871 | ++ mk_grub_rescue "${loader}" "${output}" || |
1872 | ++ fail "failed to make rescue floppy" |
1873 | ++ checksize "${output}" -lt $((2880*1024)) || |
1874 | ++ fail "output of mk_rescue was to large for floppy" |
1875 | ++ size=${_RET} |
1876 | ++ truncate --size 2880K "${output}" || |
1877 | ++ fail "failed to pad ${output} to 2880K" |
1878 | ++ echo "created ${mode} loader in ${output} (payload $size)" |
1879 | ++ ;; |
1880 | ++ grub-rescue-cdrom) |
1881 | ++ mk_grub_rescue "${loader}" "${output}" || |
1882 | ++ fail "failed to make rescue cdrom" |
1883 | ++ echo "created ${mode} loader in ${output}" |
1884 | ++ ;; |
1885 | ++esac |
1886 | ++ |
1887 | ++[ $? -eq 0 ] || fail "failed to create loader" |
1888 | |
1889 | === modified file 'debian/patches/series' |
1890 | --- debian/patches/series 2010-07-21 17:27:10 +0000 |
1891 | +++ debian/patches/series 2010-07-30 21:11:15 +0000 |
1892 | @@ -14,3 +14,4 @@ |
1893 | 18-priv_security.patch |
1894 | 20-brute-force-webui.patch |
1895 | 21-eucalyptus-1.7-with-gwt-1.6.4.patch |
1896 | +22-uec-multiboot-kvm.patch |
1897 | |
1898 | === modified file 'node/handlers.c' |
1899 | --- node/handlers.c 2010-07-21 17:27:10 +0000 |
1900 | +++ node/handlers.c 2010-07-30 21:11:15 +0000 |
1901 | @@ -380,6 +380,7 @@ |
1902 | char **xml) |
1903 | { |
1904 | char buf [MAX_PATH]; |
1905 | + char patharg [MAX_PATH]; |
1906 | |
1907 | snprintf(buf, MAX_PATH, "%s", gen_libvirt_cmd_path); |
1908 | if (strnlen(ramdiskId, CHAR_BUFFER_SIZE)) { |
1909 | @@ -395,6 +396,9 @@ |
1910 | if (params->disk > 0) { /* TODO: get this info from scMakeImage */ |
1911 | strncat (buf, " --ephemeral", MAX_PATH); |
1912 | } |
1913 | + snprintf(buf+strnlen(buf,MAX_PATH), MAX_PATH-strnlen(buf,MAX_PATH), |
1914 | + " --basepath='%s'", disk_path); |
1915 | + |
1916 | * xml = system_output (buf); |
1917 | if ( ( * xml ) == NULL ) { |
1918 | logprintfl (EUCAFATAL, "%s: %s\n", gen_libvirt_cmd_path, strerror (errno)); |
1919 | |
1920 | === modified file 'tools/Makefile' |
1921 | --- tools/Makefile 2010-07-21 17:27:10 +0000 |
1922 | +++ tools/Makefile 2010-07-30 21:11:15 +0000 |
1923 | @@ -47,6 +47,7 @@ |
1924 | @$(INSTALL) -m 755 connect_iscsitarget.pl $(DESTDIR)$(datarootdir)/eucalyptus |
1925 | @$(INSTALL) -m 755 disconnect_iscsitarget.pl $(DESTDIR)$(datarootdir)/eucalyptus |
1926 | @$(INSTALL) -m 755 get_iscsitarget.pl $(DESTDIR)$(datarootdir)/eucalyptus |
1927 | + @$(INSTALL) -m 755 mk-mb-loader $(DESTDIR)$(datarootdir)/eucalyptus |
1928 | |
1929 | uninstall: |
1930 | @$(RM) -f $(DESTDIR)$(etcdir)/init.d/eucalyptus-cloud |
1931 | @@ -68,4 +69,5 @@ |
1932 | @$(RM) -f $(DESTDIR)$(sbindir)/euca_conf |
1933 | @$(RM) -f $(DESTDIR)/etc/bash_completion.d/euca_conf |
1934 | @$(RM) -f $(DESTDIR)$(sbindir)/euca_sync_key |
1935 | + @$(RM) -f $(DESTDIR)$(datarootdir)/eucalyptus/mk-mb-loader |
1936 | |
1937 | |
1938 | === modified file 'tools/gen_kvm_libvirt_xml' |
1939 | --- tools/gen_kvm_libvirt_xml 2010-07-21 17:27:10 +0000 |
1940 | +++ tools/gen_kvm_libvirt_xml 2010-07-30 21:11:15 +0000 |
1941 | @@ -76,6 +76,8 @@ |
1942 | our $local_kvm=""; |
1943 | our $use_virtio_net = 0; |
1944 | our $use_virtio_root = 0; |
1945 | +our $base_path = ""; |
1946 | +our $multi_boot_floppy = 0; |
1947 | |
1948 | if ( -x "/usr/bin/kvm" ) { |
1949 | $local_kvm="/usr/bin/kvm"; |
1950 | @@ -90,24 +92,39 @@ |
1951 | 'ephemeral' => sub { }, # option ignored |
1952 | 'virtionet' => sub { $use_virtio_net = 1; }, |
1953 | 'virtioroot' => sub { $use_virtio_root = 1; }, |
1954 | + 'basepath=s' => \$base_path, |
1955 | ) or exit (1); |
1956 | |
1957 | +if ($base_path && &is_multiboot_img($base_path . "/kernel") && |
1958 | + ! $use_virtio_root ) { |
1959 | + $multi_boot_floppy = 1; |
1960 | +} |
1961 | + |
1962 | print <<EOF; |
1963 | <domain type='kvm'> |
1964 | <name>NAME</name> |
1965 | <os> |
1966 | <type>hvm</type> |
1967 | - <kernel>BASEPATH/kernel</kernel> |
1968 | EOF |
1969 | |
1970 | -if ( $use_ramdisk ) { |
1971 | - print " <initrd>BASEPATH/ramdisk</initrd>\n"; |
1972 | -} |
1973 | - |
1974 | -if ( $use_virtio_root ) { |
1975 | - print " <cmdline>root=/dev/vda1 console=ttyS0</cmdline>\n" |
1976 | +if ( $multi_boot_floppy ) { |
1977 | + my $mb_load_cmd = "/usr/share/eucalyptus/mk-mb-loader " . |
1978 | + "'" . $base_path . "/kernel' '" . $base_path . "/loader' 2>&1"; |
1979 | + my $mb_out = `$mb_load_cmd`; |
1980 | + if ( $? != 0 ) { print("failed to make loader\n${mb_out}\n"); exit(1); } |
1981 | + print " <boot dev='fd'/>\n"; |
1982 | + print " <boot dev='hd'/>\n"; |
1983 | } else { |
1984 | - print " <cmdline>root=/dev/sda1 console=ttyS0</cmdline>\n" |
1985 | + print " <kernel>BASEPATH/kernel</kernel>\n"; |
1986 | + if ( $use_ramdisk ) { |
1987 | + print " <initrd>BASEPATH/ramdisk</initrd>\n"; |
1988 | + } |
1989 | + |
1990 | + if ( $use_virtio_root ) { |
1991 | + print " <cmdline>root=/dev/vda1 console=ttyS0</cmdline>\n" |
1992 | + } else { |
1993 | + print " <cmdline>root=/dev/sda1 console=ttyS0</cmdline>\n" |
1994 | + } |
1995 | } |
1996 | |
1997 | print <<EOF; |
1998 | @@ -121,6 +138,15 @@ |
1999 | <emulator>$local_kvm</emulator> |
2000 | EOF |
2001 | |
2002 | +if ( $multi_boot_floppy ) { |
2003 | + print <<EOF |
2004 | + <disk type='file' device='floppy'> |
2005 | + <source file='BASEPATH/loader'/> |
2006 | + <target dev='fda' bus='fdc'/> |
2007 | + </disk> |
2008 | +EOF |
2009 | +} |
2010 | + |
2011 | if ( $use_virtio_root ) { |
2012 | print <<EOF; |
2013 | <disk type='file' device='disk'> |
2014 | @@ -163,3 +189,16 @@ |
2015 | </devices> |
2016 | </domain> |
2017 | EOF |
2018 | + |
2019 | +# this needs to be improved greatly, but the intent is |
2020 | +# to determine if this is multiboot image or not. |
2021 | +# grub-0.97 provide 'mbchk' that would have been great, that |
2022 | +# is not available in grub2 |
2023 | +sub is_multiboot_img |
2024 | +{ |
2025 | + my $kpath=$_[0]; |
2026 | + if (! (-s $kpath)) { return(0); } |
2027 | + system("/usr/bin/file '" . $kpath . "' | grep -q 'Linux kernel'"); |
2028 | + if ($? == 0) { return(0); } |
2029 | + return(1) |
2030 | +} |
2031 | |
2032 | === added file 'tools/mk-mb-loader' |
2033 | --- tools/mk-mb-loader 1970-01-01 00:00:00 +0000 |
2034 | +++ tools/mk-mb-loader 2010-07-30 21:11:15 +0000 |
2035 | @@ -0,0 +1,113 @@ |
2036 | +#!/bin/sh |
2037 | +# vi: ts=4 noexpandtab |
2038 | +# |
2039 | +# Copyright (C) 2010 Canonical Ltd. |
2040 | +# |
2041 | +# Authors: Scott Moser <smoser@canonical.com> |
2042 | +# |
2043 | +# This program is free software: you can redistribute it and/or modify |
2044 | +# it under the terms of the GNU General Public License as published by |
2045 | +# the Free Software Foundation, version 3 of the License. |
2046 | +# |
2047 | +# This program is distributed in the hope that it will be useful, |
2048 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2049 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2050 | +# GNU General Public License for more details. |
2051 | +# |
2052 | +# You should have received a copy of the GNU General Public License |
2053 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2054 | + |
2055 | +TEMP_D="" |
2056 | + |
2057 | +error() { echo "$@" 1>&2; } |
2058 | +fail() { [ $# -eq 0 ] || error "$@"; exit 1; } |
2059 | +Usage() { |
2060 | + cat <<EOF |
2061 | +Usage: ${0##*/} loader.img output.img |
2062 | + Create a multiboot floppy image that will multiboot 'loader.img' |
2063 | + where loader.img is a multiboot complient loader |
2064 | + |
2065 | + The output.img file can then be booted with |
2066 | + kvm -fda output.img -boot a -drive ... |
2067 | + and will load 'loader.img' |
2068 | +EOF |
2069 | +} |
2070 | +bad_Usage() { Usage 1>&2; fail "$@"; } |
2071 | +cleanup() { |
2072 | + [ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}" |
2073 | +} |
2074 | + |
2075 | +getsize() { |
2076 | + local f="$1" size="" |
2077 | + size=$(ls -l "${f}" 2>/dev/null | awk '{print $5}') && |
2078 | + [ -n "${size}" ] && _RET=${size} && return 0 |
2079 | +} |
2080 | +checksize() { |
2081 | + getsize "$1" || return 1 |
2082 | + [ "${_RET}" "$2" "$3" ] |
2083 | +} |
2084 | + |
2085 | +mk_grub_rescue() { |
2086 | + local input=${1} output=${2} |
2087 | + local bdir="${TEMP_D}/bdir" |
2088 | + local err="${TEMP_D}/err" |
2089 | + local modules="configfile" |
2090 | + local modules="" |
2091 | + mkdir "${bdir}" && |
2092 | + mkdir -p "${bdir}/boot/grub" && |
2093 | + cp "${input}" "${bdir}/boot/grub/loader.img" && |
2094 | + cat > "${bdir}/boot/grub/grub.cfg" <<EOF |
2095 | +multiboot /boot/grub/loader.img |
2096 | +boot |
2097 | +EOF |
2098 | + [ $? -eq 0 ] || return |
2099 | + grub-mkrescue --output="${output}" \ |
2100 | + ${modules:+"--modules=${modules}"} "${bdir}" > "${err}" 2>&1 || |
2101 | + { cat "${err}" 1>&2; return 1; } |
2102 | +} |
2103 | + |
2104 | +short_opts="h" |
2105 | +long_opts="help" |
2106 | +getopt_out=$(getopt --name "${0##*/}" \ |
2107 | + --options "${short_opts}" --long "${long_opts}" -- "$@") && |
2108 | + eval set -- "${getopt_out}" || |
2109 | + bad_Usage |
2110 | + |
2111 | +mode="grub-rescue-floppy" |
2112 | +while [ $# -ne 0 ]; do |
2113 | + cur=${1}; next=${2}; |
2114 | + case "$cur" in |
2115 | + -h|--help) Usage; exit 0;; |
2116 | + --) shift; break;; |
2117 | + esac |
2118 | + shift; |
2119 | +done |
2120 | + |
2121 | +[ $# -eq 2 ] || bad_Usage "must multiboot loader input and output file" |
2122 | + |
2123 | +TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/.${0##*/}.XXXXXX") || |
2124 | + fail "failed to make tempd" |
2125 | +trap cleanup EXIT |
2126 | + |
2127 | +loader=${1} |
2128 | +output=${2} |
2129 | + |
2130 | +case "${mode}" in |
2131 | + grub-rescue-floppy) |
2132 | + mk_grub_rescue "${loader}" "${output}" || |
2133 | + fail "failed to make rescue floppy" |
2134 | + checksize "${output}" -lt $((2880*1024)) || |
2135 | + fail "output of mk_rescue was to large for floppy" |
2136 | + size=${_RET} |
2137 | + truncate --size 2880K "${output}" || |
2138 | + fail "failed to pad ${output} to 2880K" |
2139 | + echo "created ${mode} loader in ${output} (payload $size)" |
2140 | + ;; |
2141 | + grub-rescue-cdrom) |
2142 | + mk_grub_rescue "${loader}" "${output}" || |
2143 | + fail "failed to make rescue cdrom" |
2144 | + echo "created ${mode} loader in ${output}" |
2145 | + ;; |
2146 | +esac |
2147 | + |
2148 | +[ $? -eq 0 ] || fail "failed to create loader" |
2149 | |
2150 | === modified file 'util/wrappers.conf' |
2151 | --- util/wrappers.conf 2010-03-23 19:32:58 +0000 |
2152 | +++ util/wrappers.conf 2010-07-30 21:11:15 +0000 |
2153 | @@ -20,6 +20,7 @@ |
2154 | gen_kvm_libvirt_xml /usr/share/eucalyptus/gen_kvm_libvirt_xml 0 |
2155 | gen_libvirt_xml /usr/share/eucalyptus/gen_libvirt_xml 0 |
2156 | detach.pl /usr/share/eucalyptus/detach.pl 0 |
2157 | +mk-mb-loader /usr/share/eucalyptus/mk-mb-loader 0 |
2158 | # Services |
2159 | powernap /usr/sbin/powernap-now 0 |
2160 | # LVM management |
This has been pushed to lp:~ubuntu-core-dev/ubuntu/maverick/eucalyptus/devel