Merge lp:~smoser/ubuntu/maverick/eucalyptus/maverick.bug611144 into lp:ubuntu/maverick/eucalyptus

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
Reviewer Review Type Date Requested Status
Dave Walker (community) Approve
Ubuntu branches Pending
Review via email: mp+31249@code.launchpad.net
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.

Revision history for this message
Dave Walker (davewalker) wrote :
review: Approve

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

Subscribers

People subscribed via source and target branches