~ubuntu-branches/ubuntu/natty/eucalyptus/natty-updates

1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
1
/*
2
Copyright (c) 2009  Eucalyptus Systems, Inc.	
3
4
This program is free software: you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by 
6
the Free Software Foundation, only version 3 of the License.  
7
 
8
This file is distributed in the hope that it will be useful, but WITHOUT
9
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11
for more details.  
12
13
You should have received a copy of the GNU General Public License along
14
with this program.  If not, see <http://www.gnu.org/licenses/>.
15
 
16
Please contact Eucalyptus Systems, Inc., 130 Castilian
17
Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/> 
18
if you need additional information or have any questions.
19
20
This file may incorporate work covered under the following copyright and
21
permission notice:
22
23
  Software License Agreement (BSD License)
24
25
  Copyright (c) 2008, Regents of the University of California
26
  
27
28
  Redistribution and use of this software in source and binary forms, with
29
  or without modification, are permitted provided that the following
30
  conditions are met:
31
32
    Redistributions of source code must retain the above copyright notice,
33
    this list of conditions and the following disclaimer.
34
35
    Redistributions in binary form must reproduce the above copyright
36
    notice, this list of conditions and the following disclaimer in the
37
    documentation and/or other materials provided with the distribution.
38
39
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
40
  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41
  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
42
  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
43
  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
44
  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
45
  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
46
  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
47
  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
48
  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
49
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF
50
  THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE
51
  LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS
52
  SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
53
  IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA
54
  BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN
55
  THE REGENTS’ DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT
56
  OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR
57
  WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH
58
  ANY SUCH LICENSES OR RIGHTS.
59
*/
1 by Soren Hansen
Import upstream version 1.5~bzr139
60
#include <stdio.h>
61
#include <stdlib.h>
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
62
#define __USE_GNU
1 by Soren Hansen
Import upstream version 1.5~bzr139
63
#include <string.h> /* strlen, strcpy */
64
#include <time.h>
65
#include <limits.h> /* INT_MAX */
66
#include <sys/types.h> /* fork */
67
#include <sys/wait.h> /* waitpid */
68
#include <unistd.h>
69
#include <fcntl.h>
70
#include <assert.h>
71
#include <errno.h>
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
72
#define _FILE_OFFSET_BITS 64
1 by Soren Hansen
Import upstream version 1.5~bzr139
73
#include <sys/stat.h>
74
#include <pthread.h>
75
#include <sys/vfs.h> /* statfs */
76
#include <signal.h> /* SIGINT */
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
77
#include <linux/limits.h>
78
#ifndef MAX_PATH
79
#define MAX_PATH 4096
80
#endif
1 by Soren Hansen
Import upstream version 1.5~bzr139
81
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
82
#include "eucalyptus-config.h"
1 by Soren Hansen
Import upstream version 1.5~bzr139
83
#include "ipc.h"
84
#include "misc.h"
85
#define HANDLERS_FANOUT
86
#include <handlers.h>
87
#include <storage.h>
88
#include <eucalyptus.h>
89
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
90
#define MONITORING_PERIOD (5)
91
92
/* used by lower level handlers */
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
93
sem *hyp_sem;	/* semaphore for serializing domain creation */
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
94
sem *inst_sem;	/* guarding access to global instance structs */
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
95
sem *addkey_sem;	/* guarding access to global instance structs */
96
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
97
bunchOfInstances *global_instances = NULL; 
98
1 by Soren Hansen
Import upstream version 1.5~bzr139
99
// declarations of available handlers
100
extern struct handlers xen_libvirt_handlers;
101
extern struct handlers kvm_libvirt_handlers;
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
102
extern struct handlers default_libvirt_handlers;
103
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
104
const int staging_cleanup_threshold = 60 * 60 * 2; /* after this many seconds any STAGING domains will be cleaned up */
105
const int booting_cleanup_threshold = 60; /* after this many seconds any BOOTING domains will be cleaned up */
106
const int teardown_state_duration = 180; /* after this many seconds in TEARDOWN state (no resources), we'll forget about the instance */
1 by Soren Hansen
Import upstream version 1.5~bzr139
107
108
// a NULL-terminated array of available handlers
109
static struct handlers * available_handlers [] = {
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
110
	&default_libvirt_handlers,
111
	&xen_libvirt_handlers,
112
	&kvm_libvirt_handlers,
113
	NULL
1 by Soren Hansen
Import upstream version 1.5~bzr139
114
};
115
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
116
struct nc_state_t nc_state;
117
118
/* utilitarian functions used in the lower level handlers */
119
int
120
get_value(	char *s,
121
		const char *name,
122
		long long * valp)
123
{
124
	char buf [CHAR_BUFFER_SIZE];
125
126
	if (s==NULL || name==NULL || valp==NULL)
127
		return ERROR;
128
	snprintf (buf, CHAR_BUFFER_SIZE, "%s=%%lld", name);
129
	return (sscanf_lines (s, buf, valp)==1 ? OK : ERROR);
130
}
131
132
void libvirt_error_handler (	void *userData,
133
				virErrorPtr error)
134
{
135
	if ( error==NULL) {
136
		logprintfl (EUCAERROR, "libvirt error handler was given a NULL pointer\n");
137
	} else {
138
		logprintfl (EUCAERROR, "libvirt: %s (code=%d)\n", error->message, error->code);
139
	}
140
}
141
142
int convert_dev_names(	char *localDev,
143
			char *localDevReal,
144
			char *localDevTag) 
145
{
146
    bzero(localDevReal, 32);
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
147
    if (strchr(localDev, '/') != NULL) {
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
148
        sscanf(localDev, "/dev/%s", localDevReal);
149
    } else {
150
        snprintf(localDevReal, 32, "%s", localDev);
151
    }
152
    if (localDevReal[0] == 0) {
153
        logprintfl(EUCAERROR, "bad input parameter for localDev (should be /dev/XXX): '%s'\n", localDev);
154
        return(ERROR);
155
    }
156
    if (localDevTag) {
157
        bzero(localDevTag, 256);
158
        snprintf(localDevTag, 256, "unknown,requested:%s", localDev);
159
    }
160
161
    return 0;
162
}
163
164
void
165
print_running_domains (void)
166
{
167
	bunchOfInstances * head;
168
	char buf [CHAR_BUFFER_SIZE] = "";
169
170
	sem_p (inst_sem);
171
	for ( head=global_instances; head; head=head->next ) {
172
		ncInstance * instance = head->instance;
1.1.27 by Dustin Kirkland
Import upstream version 1.6.2~bzr1120
173
		if (instance->state==STAGING || instance->state==BOOTING
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
174
				|| instance->state==RUNNING
175
				|| instance->state==BLOCKED
176
				|| instance->state==PAUSED) {
177
			strcat (buf, " ");
178
			strcat (buf, instance->instanceId);
179
		}
180
	}
181
	sem_v (inst_sem);
182
	logprintfl (EUCAINFO, "currently running/booting: %s\n", buf);
183
}
184
185
virConnectPtr *
186
check_hypervisor_conn()
187
{
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
188
	if (nc_state.conn == NULL || virConnectGetURI(nc_state.conn) == NULL) {
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
189
		nc_state.conn = virConnectOpen (nc_state.uri);
190
		if (nc_state.conn == NULL) {
191
			logprintfl (EUCAFATAL, "Failed to connect to %s\n", nc_state.uri);
192
			return NULL;
193
		}
194
	}
195
196
	return &(nc_state.conn);
197
}
198
199
200
void change_state(	ncInstance *instance,
201
			instance_states state)
202
{
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
203
    int old_state = instance->state;
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
204
    instance->state = (int) state;
205
    switch (state) { /* mapping from NC's internal states into external ones */
1.1.27 by Dustin Kirkland
Import upstream version 1.6.2~bzr1120
206
    case STAGING:
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
207
    case BOOTING:
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
208
    case CANCELED:
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
209
        instance->stateCode = PENDING;
210
        break;
211
    case RUNNING:
212
    case BLOCKED:
213
    case PAUSED:
214
    case SHUTDOWN:
215
    case SHUTOFF:
216
    case CRASHED:
217
        instance->stateCode = EXTANT;
218
	instance->retries = LIBVIRT_QUERY_RETRIES;
219
        break;
220
    case TEARDOWN:
221
        instance->stateCode = TEARDOWN;
222
        break;
223
    default:
224
        logprintfl (EUCAERROR, "error: change_sate(): unexpected state (%d) for instance %s\n", instance->state, instance->instanceId);        
225
        return;
226
    }
227
228
    strncpy(instance->stateName, instance_state_names[instance->stateCode], CHAR_BUFFER_SIZE);
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
229
    if (old_state != state) {
230
        logprintfl (EUCADEBUG, "state change for instance %s: %s -> %s (%s)\n", 
231
                    instance->instanceId, 
232
                    instance_state_names [old_state],
233
                    instance_state_names [instance->state],
234
                    instance_state_names [instance->stateCode]);
235
    }
236
}
237
238
// waits indefinitely until a state transition takes place
239
// (timeouts are implemented in the monitoring thread) and
240
// returns 0 if from_state->to_state transition takes place
241
// and 1 otherwise
242
int 
243
wait_state_transition (ncInstance * instance, 
244
		       instance_states from_state,
245
		       instance_states to_state) 
246
{
247
  while (1) {
248
    instance_states current_state = instance->state;
249
    if (current_state == to_state ) 
250
      return 0;
251
    if (current_state != from_state )
252
      return 1;
253
    sleep (MONITORING_PERIOD); // no point in checking more frequently
254
  }
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
255
}
256
257
static void
258
refresh_instance_info(	struct nc_state_t *nc,
259
			ncInstance *instance)
260
{
261
    int now = instance->state;
262
    
263
    if (! check_hypervisor_conn ())
264
	    return;
265
1.1.27 by Dustin Kirkland
Import upstream version 1.6.2~bzr1120
266
    /* no need to bug for domains without state on Hypervisor */
267
    if (now==TEARDOWN || now==STAGING)
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
268
        return;
269
    
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
270
    sem_p(hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
271
    virDomainPtr dom = virDomainLookupByName (nc_state.conn, instance->instanceId);
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
272
    sem_v(hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
273
    if (dom == NULL) { /* hypervisor doesn't know about it */
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
274
      if (now==RUNNING ||
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
275
            now==BLOCKED ||
276
            now==PAUSED ||
277
            now==SHUTDOWN) {
278
            /* Most likely the user has shut it down from the inside */
279
            if (instance->retries) {
280
		instance->retries--;
281
		logprintfl (EUCAWARN, "warning: hypervisor failed to find domain %s, will retry %d more times\n", instance->instanceId, instance->retries);	
282
            } else {
283
            	logprintfl (EUCAWARN, "warning: hypervisor failed to find domain %s, assuming it was shut off\n", instance->instanceId);
284
            	change_state (instance, SHUTOFF);
285
            }
286
        }
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
287
        /* else 'now' stays in SHUTFOFF, BOOTING, CANCELED, or CRASHED */
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
288
        return;
289
    }
290
    virDomainInfo info;
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
291
    sem_p(hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
292
    int error = virDomainGetInfo(dom, &info);
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
293
    sem_v(hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
294
    if (error < 0 || info.state == VIR_DOMAIN_NOSTATE) {
295
        logprintfl (EUCAWARN, "warning: failed to get informations for domain %s\n", instance->instanceId);
296
        /* what to do? hopefully we'll find out more later */
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
297
	sem_p(hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
298
        virDomainFree (dom);
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
299
	sem_v(hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
300
        return;
301
    } 
302
    int xen = info.state;
303
304
    switch (now) {
305
    case BOOTING:
306
    case RUNNING:
307
    case BLOCKED:
308
    case PAUSED:
309
        /* change to state, whatever it happens to be */
310
        change_state (instance, xen);
311
        break;
312
    case SHUTDOWN:
313
    case SHUTOFF:
314
    case CRASHED:
315
        if (xen==RUNNING ||
316
            xen==BLOCKED ||
317
            xen==PAUSED) {
318
            /* cannot go back! */
319
            logprintfl (EUCAWARN, "warning: detected prodigal domain %s, terminating it\n", instance->instanceId);
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
320
            sem_p (hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
321
            virDomainDestroy (dom);
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
322
            sem_v (hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
323
        } else {
324
            change_state (instance, xen);
325
        }
326
        break;
327
    default:
328
        logprintfl (EUCAERROR, "error: refresh...(): unexpected state (%d) for instance %s\n", now, instance->instanceId);
329
        return;
330
    }
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
331
    sem_p(hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
332
    virDomainFree(dom);
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
333
    sem_v(hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
334
335
    /* if instance is running, try to find out its IP address */
336
    if (instance->state==RUNNING ||
337
        instance->state==BLOCKED ||
338
        instance->state==PAUSED) {
339
        char *ip=NULL;
340
        int rc;
341
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
342
        if (!strncmp(instance->ncnet.publicIp, "0.0.0.0", 24)) {
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
343
	  if (!strcmp(nc_state.vnetconfig->mode, "SYSTEM") || !strcmp(nc_state.vnetconfig->mode, "STATIC")) {
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
344
            rc = mac2ip(nc_state.vnetconfig, instance->ncnet.privateMac, &ip);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
345
            if (!rc) {
1.1.26 by Thierry Carrez
Import upstream version 1.6.2~bzr1113
346
	      if(ip) {
347
	        logprintfl (EUCAINFO, "discovered public IP %s for instance %s\n", ip, instance->instanceId);
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
348
	        strncpy(instance->ncnet.publicIp, ip, 24);
1.1.26 by Thierry Carrez
Import upstream version 1.6.2~bzr1113
349
	        free(ip);
350
	      }
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
351
            }
352
	  }
353
        }
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
354
        if (!strncmp(instance->ncnet.privateIp, "0.0.0.0", 24)) {
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
355
            rc = mac2ip(nc_state.vnetconfig, instance->ncnet.privateMac, &ip);
356
            if (!rc) {
1.1.26 by Thierry Carrez
Import upstream version 1.6.2~bzr1113
357
		if(ip) {
358
                  logprintfl (EUCAINFO, "discovered private IP %s for instance %s\n", ip, instance->instanceId);
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
359
                  strncpy(instance->ncnet.privateIp, ip, 24);
1.1.26 by Thierry Carrez
Import upstream version 1.6.2~bzr1113
360
	          free(ip);
361
		}
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
362
            }
363
        }
364
    }
365
}
366
367
int
368
get_instance_xml(	const char *gen_libvirt_cmd_path,
369
			char *userId,
370
			char *instanceId,
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
371
			char *ramdiskId,
372
			char *kernelId,
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
373
			char *disk_path,
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
374
			virtualMachine *params,
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
375
			char *privMac,
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
376
			//			char *privIp,
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
377
			char *brname,
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
378
			int use_virtio_net,
379
			int use_virtio_root,
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
380
			char **xml)
381
{
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
382
    char buf [MAX_PATH];
157 by Dave Walker (Daviey), Dave Walker (Daviey), Scott Moser
[ Dave Walker (Daviey) ]
383
    char patharg [MAX_PATH];
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
384
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
385
    snprintf(buf, MAX_PATH, "%s", gen_libvirt_cmd_path);
386
    if (strnlen(ramdiskId, CHAR_BUFFER_SIZE)) {
1.1.49 by Dave Walker (Daviey)
Import upstream version 2.0.1+bzr1256
387
        strncat(buf, " --ramdisk", MAX_PATH - strlen(buf) - 1);
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
388
    }
389
    if (use_virtio_net) {
1.1.49 by Dave Walker (Daviey)
Import upstream version 2.0.1+bzr1256
390
        strncat(buf, " --virtionet", MAX_PATH - strlen(buf) - 1);
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
391
    }
392
    if (use_virtio_root) {
1.1.49 by Dave Walker (Daviey)
Import upstream version 2.0.1+bzr1256
393
        strncat(buf, " --virtioroot", MAX_PATH - strlen(buf) - 1);
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
394
    }
395
    
396
    if (params->disk > 0) { /* TODO: get this info from scMakeImage */
1.1.49 by Dave Walker (Daviey)
Import upstream version 2.0.1+bzr1256
397
        strncat (buf, " --ephemeral", MAX_PATH - strlen(buf) - 1);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
398
    }
157 by Dave Walker (Daviey), Dave Walker (Daviey), Scott Moser
[ Dave Walker (Daviey) ]
399
    snprintf(buf+strnlen(buf,MAX_PATH), MAX_PATH-strnlen(buf,MAX_PATH),
400
             " --basepath='%s'", disk_path);
401
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
402
    * xml = system_output (buf);
403
    if ( ( * xml ) == NULL ) {
404
        logprintfl (EUCAFATAL, "%s: %s\n", gen_libvirt_cmd_path, strerror (errno));
405
        return ERROR;
406
    }
407
    
408
    /* the tags better be not substring of other tags: BA will substitute
409
     * ABABABAB */
410
    replace_string (xml, "BASEPATH", disk_path);
411
    replace_string (xml, "SWAPPATH", disk_path);
412
    replace_string (xml, "NAME", instanceId);
413
    replace_string (xml, "PRIVMACADDR", privMac);
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
414
    //    replace_string (xml, "PUBMACADDR", pubMac);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
415
    replace_string (xml, "BRIDGEDEV", brname);
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
416
    snprintf(buf, CHAR_BUFFER_SIZE, "%d", params->mem * 1024); /* because libvirt wants memory in Kb, while we use Mb */
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
417
    replace_string (xml, "MEMORY", buf);
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
418
    snprintf(buf, CHAR_BUFFER_SIZE, "%d", params->cores);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
419
    replace_string (xml, "VCPUS", buf);
420
    
421
    return 0;
422
}
423
424
425
void *
426
monitoring_thread (void *arg)
427
{
428
	int i;
429
	struct nc_state_t *nc;
430
431
	if (arg == NULL) {
432
		logprintfl (EUCAFATAL, "NULL parameter!\n");
433
		return NULL;
434
	}
435
	nc = (struct nc_state_t*)arg;
436
437
	logprintfl (EUCADEBUG, "Starting monitoring thread\n!\n");
438
439
    for (;;) {
440
        bunchOfInstances *head;
441
        time_t now = time(NULL);
442
        sem_p (inst_sem);
443
444
        for ( head = global_instances; head; head = head->next ) {
445
            ncInstance * instance = head->instance;
446
447
            /* query for current state, if any */
448
	    refresh_instance_info (nc, instance);
449
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
450
            /* don't touch running or canceled threads */
1.1.27 by Dustin Kirkland
Import upstream version 1.6.2~bzr1120
451
            if (instance->state!=STAGING && instance->state!=BOOTING && 
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
452
                instance->state!=SHUTOFF &&
453
                instance->state!=SHUTDOWN &&
454
                instance->state!=TEARDOWN) continue;
455
456
            if (instance->state==TEARDOWN) {
1.1.27 by Dustin Kirkland
Import upstream version 1.6.2~bzr1120
457
                /* it's been long enough, we can forget the instance */
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
458
                if ((now - instance->terminationTime)>teardown_state_duration) {
459
                    remove_instance (&global_instances, instance);
460
                    logprintfl (EUCAINFO, "forgetting about instance %s\n", instance->instanceId);
461
                    free_instance (&instance);
462
		    break;	/* need to get out since the list changed */
463
                }
464
                continue;
465
            }
466
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
467
	    // time out logic for STAGING or BOOTING instances
468
            if (instance->state==STAGING  
469
		&& (now - instance->launchTime)   < staging_cleanup_threshold) continue; // hasn't been long enough, spare it
470
            if (instance->state==BOOTING  
471
		&& (now - instance->bootTime)     < booting_cleanup_threshold) continue;
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
472
            
473
            /* ok, it's been condemned => destroy the files */
474
            if (!nc_state.save_instance_files) {
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
475
				logprintfl (EUCAINFO, "cleaning up state for instance %s\n", instance->instanceId);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
476
	      if (scCleanupInstanceImage(instance->userId, instance->instanceId)) {
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
477
                logprintfl (EUCAWARN, "warning: failed to cleanup instance image %s\n", instance->instanceId);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
478
	      }
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
479
			} else {
480
				logprintfl (EUCAINFO, "cleaning up state for instance %s (but keeping the files)\n", instance->instanceId);
481
			}
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
482
            
483
            /* check to see if this is the last instance running on vlan */
484
            int left = 0;
485
            bunchOfInstances * vnhead;
486
            for (vnhead = global_instances; vnhead; vnhead = vnhead->next ) {
487
                ncInstance * vninstance = vnhead->instance;
488
                if (vninstance->ncnet.vlan == (instance->ncnet).vlan 
489
                    && strcmp(instance->instanceId, vninstance->instanceId)) {
490
                    left++;
491
                }
492
            }
493
            if (left==0) {
494
                logprintfl (EUCAINFO, "stopping the network (vlan=%d)\n", (instance->ncnet).vlan);
495
                vnetStopNetwork (nc_state.vnetconfig, (instance->ncnet).vlan, NULL, NULL);
496
            }
497
            change_state (instance, TEARDOWN); /* TEARDOWN = no more resources */
498
            instance->terminationTime = time (NULL);
499
        }
500
        sem_v (inst_sem);
501
502
	if (head) {
503
		/* we got out because of modified list, no need to sleep
504
		 * now */
505
		continue;
506
	}
507
        
508
        sleep (MONITORING_PERIOD);
509
    }
510
    
511
    return NULL;
512
}
513
514
515
void *startup_thread (void * arg)
516
{
517
    ncInstance * instance = (ncInstance *)arg;
518
    virDomainPtr dom = NULL;
1.1.49 by Dave Walker (Daviey)
Import upstream version 2.0.1+bzr1256
519
    char *disk_path=NULL, *xml=NULL;
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
520
    char *brname=NULL;
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
521
    int error, i;
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
522
    
523
    if (! check_hypervisor_conn ()) {
524
        logprintfl (EUCAFATAL, "could not start instance %s, abandoning it\n", instance->instanceId);
525
        change_state (instance, SHUTOFF);
526
        return NULL;
527
    }
528
    
529
    error = vnetStartNetwork (nc_state.vnetconfig, instance->ncnet.vlan, NULL, NULL, &brname);
530
    if ( error ) {
531
        logprintfl (EUCAFATAL, "start network failed for instance %s, terminating it\n", instance->instanceId);
532
        change_state (instance, SHUTOFF);
533
        return NULL;
534
    }
535
    logprintfl (EUCAINFO, "network started for instance %s\n", instance->instanceId);
536
    
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
537
    error = scMakeInstanceImage (nc_state.home, 
538
				 instance->userId, 
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
539
                                 instance->imageId, instance->imageURL, 
540
                                 instance->kernelId, instance->kernelURL, 
541
                                 instance->ramdiskId, instance->ramdiskURL, 
542
                                 instance->instanceId, instance->keyName, 
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
543
				 &disk_path, 
544
				 addkey_sem, nc_state.convert_to_disk,
545
				 instance->params.disk*1024);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
546
    if (error) {
547
        logprintfl (EUCAFATAL, "Failed to prepare images for instance %s (error=%d)\n", instance->instanceId, error);
548
        change_state (instance, SHUTOFF);
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
549
	if (brname) free(brname);
1.1.49 by Dave Walker (Daviey)
Import upstream version 2.0.1+bzr1256
550
        if (disk_path) free(disk_path);
551
        return NULL;
552
    }
553
    if (instance->state==TEARDOWN) { // timed out in STAGING
554
            if (disk_path) free(disk_path);
555
            if (brname) free(brname);
556
            return NULL;
557
    }
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
558
    if (instance->state==CANCELED) {
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
559
        logprintfl (EUCAFATAL, "Startup of instance %s was cancelled\n", instance->instanceId);
560
        change_state (instance, SHUTOFF);
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
561
	if (brname) free(brname);
1.1.49 by Dave Walker (Daviey)
Import upstream version 2.0.1+bzr1256
562
        if (disk_path) free(disk_path);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
563
        return NULL;
564
    }
565
    
566
    error = get_instance_xml (nc_state.gen_libvirt_cmd_path,
567
		              instance->userId, instance->instanceId, 
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
568
			      instance->ramdiskId,
569
			      instance->kernelId,
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
570
                              disk_path, 
571
                              &(instance->params), 
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
572
                              instance->ncnet.privateMac, 
573
                              brname,
574
                              nc_state.config_use_virtio_net,
575
                              nc_state.config_use_virtio_root,
576
                              &xml);
577
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
578
    if (brname) free(brname);
1.1.49 by Dave Walker (Daviey)
Import upstream version 2.0.1+bzr1256
579
    if (disk_path) free(disk_path);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
580
    if (xml) logprintfl (EUCADEBUG2, "libvirt XML config:\n%s\n", xml);
581
    if (error) {
582
        logprintfl (EUCAFATAL, "Failed to create libvirt XML config for instance %s\n", instance->instanceId);
583
        change_state (instance, SHUTOFF);
584
        return NULL;
585
    }
586
    
587
    scStoreStringToInstanceFile (instance->userId, instance->instanceId, "libvirt.xml", xml); /* for debugging */
588
    scSaveInstanceInfo(instance); /* to enable NC recovery */
589
590
    /* we serialize domain creation as hypervisors can get confused with
591
     * too many simultaneous create requests */
592
    logprintfl (EUCADEBUG2, "about to start domain %s\n", instance->instanceId);
593
    print_running_domains ();
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
594
    for (i=0; i<5 && dom == NULL; i++) {
595
      sem_p (hyp_sem);
596
      dom = virDomainCreateLinux (nc_state.conn, xml, 0);
597
      sem_v (hyp_sem);
598
    }
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
599
    if (xml) free(xml);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
600
    if (dom == NULL) {
601
        logprintfl (EUCAFATAL, "hypervisor failed to start domain\n");
602
        change_state (instance, SHUTOFF);
603
        return NULL;
604
    }
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
605
    eventlog("NC", instance->userId, "", "instanceBoot", "begin"); // TODO: bring back correlationId
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
606
    
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
607
    sem_p(hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
608
    virDomainFree(dom);
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
609
    sem_v(hyp_sem);
610
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
611
    sem_p (inst_sem);
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
612
    // check one more time for cancellation
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
613
    if (instance->state==TEARDOWN) { 
614
      // timed out in BOOTING
615
    } else if (instance->state==CANCELED || instance->state==SHUTOFF) {
616
      logprintfl (EUCAFATAL, "startup of instance %s was cancelled\n", instance->instanceId);
617
      change_state (instance, SHUTOFF);
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
618
    } else {
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
619
      logprintfl (EUCAINFO, "booting VM instance %s\n", instance->instanceId);
620
      instance->bootTime = time (NULL);
621
      change_state (instance, BOOTING);
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
622
    }
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
623
    sem_v (inst_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
624
    return NULL;
625
}
626
627
void adopt_instances()
628
{
629
	int dom_ids[MAXDOMS];
630
	int num_doms = 0;
631
	int i;
632
       	virDomainPtr dom = NULL;
633
634
	if (! check_hypervisor_conn())
635
		return;
636
        
637
	logprintfl (EUCAINFO, "looking for existing domains\n");
638
	virSetErrorFunc (NULL, libvirt_error_handler);
639
        
640
	num_doms = virConnectListDomains(nc_state.conn, dom_ids, MAXDOMS);
641
	if (num_doms == 0) {
642
		logprintfl (EUCAINFO, "no currently running domains to adopt\n");
643
		return;
644
	} if (num_doms < 0) {
645
		logprintfl (EUCAWARN, "WARNING: failed to find out about running domains\n");
646
		return;
647
	}
648
649
	for ( i=0; i<num_doms; i++) {
650
		int error;
651
		virDomainInfo info;
652
		const char * dom_name;
653
		ncInstance * instance;
654
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
655
		sem_p(hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
656
		dom = virDomainLookupByID(nc_state.conn, dom_ids[i]);
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
657
		sem_v(hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
658
		if (!dom) {
659
			logprintfl (EUCAWARN, "WARNING: failed to lookup running domain #%d, ignoring it\n", dom_ids[i]);
660
			continue;
661
		}
662
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
663
		sem_p(hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
664
		error = virDomainGetInfo(dom, &info);
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
665
		sem_v(hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
666
		if (error < 0 || info.state == VIR_DOMAIN_NOSTATE) {
667
			logprintfl (EUCAWARN, "WARNING: failed to get info on running domain #%d, ignoring it\n", dom_ids[i]);
668
			continue;
669
		}
670
671
		if (info.state == VIR_DOMAIN_SHUTDOWN ||
672
				info.state == VIR_DOMAIN_SHUTOFF ||
673
				info.state == VIR_DOMAIN_CRASHED ) {
674
			logprintfl (EUCADEBUG, "ignoring non-running domain #%d\n", dom_ids[i]);
675
			continue;
676
		}
677
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
678
		sem_p(hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
679
		if ((dom_name = virDomainGetName(dom))==NULL) {
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
680
		        sem_v(hyp_sem);
681
		        logprintfl (EUCAWARN, "WARNING: failed to get name of running domain #%d, ignoring it\n", dom_ids[i]);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
682
			continue;
683
		}
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
684
		sem_v(hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
685
686
		if (!strcmp(dom_name, "Domain-0"))
687
			continue;
688
689
		if ((instance = scRecoverInstanceInfo (dom_name))==NULL) {
690
			logprintfl (EUCAWARN, "WARNING: failed to recover Eucalyptus metadata of running domain %s, ignoring it\n", dom_name);
691
			continue;
692
		}
693
694
		change_state (instance, info.state);                    
695
		sem_p (inst_sem);
696
		int err = add_instance (&global_instances, instance);
697
		sem_v (inst_sem);
698
		if (err) {
699
			free_instance (&instance);
700
			continue;
701
		}
702
703
		logprintfl (EUCAINFO, "- adopted running domain %s from user %s\n", instance->instanceId, instance->userId);
704
		/* TODO: try to look up IPs? */
705
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
706
		sem_p(hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
707
		virDomainFree (dom);
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
708
		sem_v(hyp_sem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
709
	}
710
}
711
1 by Soren Hansen
Import upstream version 1.5~bzr139
712
static int init (void)
713
{
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
714
	static int initialized = 0;
715
	int do_warn = 0, i;
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
716
	char configFiles[2][MAX_PATH],
717
		log[MAX_PATH],
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
718
		*bridge,
719
		*hypervisor,
720
		*s,
721
	       	*tmp;
722
	struct stat mystat;
723
	struct statfs fs;
724
	struct handlers ** h; 
725
	long long fs_free_blocks = 0;
726
	long long fs_block_size  = 0;
727
	long long instances_bytes = 0;
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
728
	pthread_t tcb;
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
729
730
	if (initialized>0) /* 0 => hasn't run, -1 => failed, 1 => ok */
731
		return 0;
732
	else if (initialized<0)
733
		return 1;
734
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
735
	bzero (&nc_state, sizeof(struct nc_state_t)); // ensure that MAXes are zeroed out
736
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
737
	/* from now on we have unrecoverable failure, so no point in
738
	 * retrying to re-init */
739
	initialized = -1;
740
741
	/* read in configuration - this should be first! */
742
	tmp = getenv(EUCALYPTUS_ENV_VAR_NAME);
743
	if (!tmp) {
744
		nc_state.home[0] = '\0';
745
		do_warn = 1;
746
	} else 
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
747
		strncpy(nc_state.home, tmp, MAX_PATH);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
748
749
	/* set the minimum log for now */
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
750
	snprintf(log, MAX_PATH, "%s/var/log/eucalyptus/nc.log", nc_state.home);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
751
	logfile(log, EUCADEBUG);
752
753
	if (do_warn) 
754
		logprintfl (EUCAWARN, "env variable %s not set, using /\n", EUCALYPTUS_ENV_VAR_NAME);
755
756
	/* search for the config file */
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
757
	snprintf(configFiles[1], MAX_PATH, EUCALYPTUS_CONF_LOCATION, nc_state.home);
1.1.28 by Dustin Kirkland
Import upstream version 1.6.2~bzr1124
758
	if (stat(configFiles[1], &mystat)) {
759
		logprintfl (EUCAFATAL, "could not open configuration file %s\n", configFiles[1]);
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
760
		return 1;
761
	}
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
762
	snprintf(configFiles[0], MAX_PATH, EUCALYPTUS_CONF_OVERRIDE_LOCATION, nc_state.home);
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
763
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
764
	logprintfl (EUCAINFO, "NC is looking for configuration in %s,%s\n", configFiles[1], configFiles[0]);
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
765
766
	/* reset the log to the right value */
1.1.28 by Dustin Kirkland
Import upstream version 1.6.2~bzr1124
767
	tmp = getConfString(configFiles, 2, "LOGLEVEL");
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
768
	i = EUCADEBUG;
769
	if (tmp) {
770
		if (!strcmp(tmp,"INFO")) {i=EUCAINFO;}
771
		else if (!strcmp(tmp,"WARN")) {i=EUCAWARN;}
772
		else if (!strcmp(tmp,"ERROR")) {i=EUCAERROR;}
773
		else if (!strcmp(tmp,"FATAL")) {i=EUCAFATAL;}
774
		free(tmp);
775
	}
776
	logfile(log, i);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
777
778
#define GET_VAR_INT(var,name) \
1.1.28 by Dustin Kirkland
Import upstream version 1.6.2~bzr1124
779
        s = getConfString(configFiles, 2, name); \
780
	if (s){					\
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
781
		var = atoi(s);\
782
		free (s);\
783
	}
784
785
	GET_VAR_INT(nc_state.config_max_mem,      CONFIG_MAX_MEM);
786
	GET_VAR_INT(nc_state.config_max_disk,     CONFIG_MAX_DISK);
787
	GET_VAR_INT(nc_state.config_max_cores,    CONFIG_MAX_CORES);
788
	GET_VAR_INT(nc_state.save_instance_files, CONFIG_SAVE_INSTANCES);
789
790
	nc_state.config_network_port = NC_NET_PORT_DEFAULT;
791
	strcpy(nc_state.admin_user_id, EUCALYPTUS_ADMIN);
792
1.1.23 by Dustin Kirkland
Import upstream version 1.6.1~bzr1083
793
	hyp_sem = sem_alloc (1, "mutex");
794
	inst_sem = sem_alloc (1, "mutex");
795
	addkey_sem = sem_alloc (1, "mutex");
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
796
	if (!hyp_sem || !inst_sem) {
797
		logprintfl (EUCAFATAL, "failed to create and initialize a semaphore\n");
798
		return ERROR_FATAL;
799
	}
800
801
	/* set default in the paths. the driver will override */
802
	nc_state.config_network_path[0] = '\0';
803
	nc_state.gen_libvirt_cmd_path[0] = '\0';
804
	nc_state.xm_cmd_path[0] = '\0';
805
	nc_state.virsh_cmd_path[0] = '\0';
806
	nc_state.get_info_cmd_path[0] = '\0';
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
807
	snprintf (nc_state.rootwrap_cmd_path, MAX_PATH, EUCALYPTUS_ROOTWRAP, nc_state.home);
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
808
809
	/* prompt the SC to read the configuration too */
810
	if (scInitConfig()) {
811
		logprintfl (EUCAFATAL, "ERROR: scInitConfig() failed\n");
812
		return ERROR_FATAL;
813
	}
814
815
	/* determine the hypervisor to use */
1.1.28 by Dustin Kirkland
Import upstream version 1.6.2~bzr1124
816
	
817
	//if (get_conf_var(config, CONFIG_HYPERVISOR, &hypervisor)<1) {
818
	hypervisor = getConfString(configFiles, 2, CONFIG_HYPERVISOR);
819
	if (!hypervisor) {
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
820
		logprintfl (EUCAFATAL, "value %s is not set in the config file\n", CONFIG_HYPERVISOR);
821
		return ERROR_FATAL;
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
822
	}
823
824
	/* let's look for the right hypervisor driver */
825
	for (h = available_handlers; *h; h++ ) {
826
		if (!strncmp ((*h)->name, "default", CHAR_BUFFER_SIZE))
827
			nc_state.D = *h; 
828
		if (!strncmp ((*h)->name, hypervisor, CHAR_BUFFER_SIZE))
829
			nc_state.H = *h; 
830
	}
831
	if (nc_state.H == NULL) {
832
		logprintfl (EUCAFATAL, "requested hypervisor type (%s) is not available\n", hypervisor);
833
		free (hypervisor);
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
834
		return ERROR_FATAL;
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
835
	}
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
836
	
837
	/* only load virtio config for kvm */
838
	if (!strncmp("kvm", hypervisor, CHAR_BUFFER_SIZE) ||
839
		!strncmp("KVM", hypervisor, CHAR_BUFFER_SIZE)) {
840
		GET_VAR_INT(nc_state.config_use_virtio_net, CONFIG_USE_VIRTIO_NET);
841
		GET_VAR_INT(nc_state.config_use_virtio_disk, CONFIG_USE_VIRTIO_DISK);
842
		GET_VAR_INT(nc_state.config_use_virtio_root, CONFIG_USE_VIRTIO_ROOT);
843
	}
844
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
845
	free (hypervisor);
846
847
	/* NOTE: this is the only call which needs to be called on both
848
	 * the default and the specific handler! All the others will be
849
	 * either or */
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
850
	i = nc_state.D->doInitialize(&nc_state);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
851
	if (nc_state.H->doInitialize)
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
852
		i += nc_state.H->doInitialize(&nc_state);
853
	if (i) {
854
		logprintfl(EUCAFATAL, "ERROR: failed to initialized hypervisor driver!\n");
855
		return ERROR_FATAL;
856
	}
857
858
	/* adopt running instances */
859
	adopt_instances();
860
861
	/* setup the network */
862
	nc_state.vnetconfig = malloc(sizeof(vnetConfig));
863
	if (!nc_state.vnetconfig) {
864
		logprintfl (EUCAFATAL, "Cannot allocate vnetconfig!\n");
865
		return 1;
866
	}
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
867
	snprintf (nc_state.config_network_path, MAX_PATH, NC_NET_PATH_DEFAULT, nc_state.home);
1.1.28 by Dustin Kirkland
Import upstream version 1.6.2~bzr1124
868
	hypervisor = getConfString(configFiles, 2, "VNET_PUBINTERFACE");
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
869
	if (!hypervisor) 
1.1.28 by Dustin Kirkland
Import upstream version 1.6.2~bzr1124
870
		hypervisor = getConfString(configFiles, 2, "VNET_INTERFACE");
871
	bridge = getConfString(configFiles, 2, "VNET_BRIDGE");
872
	tmp = getConfString(configFiles, 2, "VNET_MODE");
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
873
	
1.1.19 by Dustin Kirkland
Import upstream version 1.6~bzr916
874
	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);
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
875
	if (hypervisor) free(hypervisor);
876
	if (bridge) free(bridge);
877
	if (tmp) free(tmp);
878
879
	/* cleanup from previous runs and verify integrity of
880
	 * instances directory */
881
	sem_p (inst_sem);
882
	instances_bytes = scFSCK (&global_instances);
883
	sem_v (inst_sem);
884
	if (instances_bytes < 0) {
885
		logprintfl (EUCAFATAL, "instances store failed integrity check (error=%lld)\n", instances_bytes);
886
		return ERROR_FATAL;
887
	}
888
	
889
	/* get disk max */
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
890
	strncpy(log, scGetInstancePath(), MAX_PATH);
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
891
892
	if (statfs(log, &fs) == -1) {
893
		logprintfl(EUCAWARN, "Failed to stat %s\n", log);
894
	}  else {
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
895
		nc_state.disk_max = (long long)fs.f_bsize * (long long)fs.f_bavail + instances_bytes; /* max for Euca, not total */
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
896
		nc_state.disk_max /= BYTES_PER_DISK_UNIT;
897
		if (nc_state.config_max_disk && nc_state.config_max_disk < nc_state.disk_max)
898
			nc_state.disk_max = nc_state.config_max_disk;
899
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
900
		logprintfl (EUCAINFO, "Maximum disk available: %lld (under %s)\n", nc_state.disk_max, log);
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
901
	}
902
903
	/* start the monitoring thread */
904
	if (pthread_create(&tcb, NULL, monitoring_thread, &nc_state)) {
905
		logprintfl (EUCAFATAL, "failed to spawn a monitoring thread\n");
906
		return ERROR_FATAL;
907
	}
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
908
        if (pthread_detach(tcb)) {
909
          logprintfl(EUCAFATAL, "failed to detach the monitoring thread\n");
910
          return ERROR_FATAL;
911
        }
912
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
913
914
	initialized = 1;
915
916
	return OK;
1 by Soren Hansen
Import upstream version 1.5~bzr139
917
}
918
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
919
1 by Soren Hansen
Import upstream version 1.5~bzr139
920
int doDescribeInstances (ncMetadata *meta, char **instIds, int instIdsLen, ncInstance ***outInsts, int *outInstsLen)
921
{
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
922
        int ret, len, i;
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
923
	char *file_name;
924
	FILE *f;
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
925
	long long used_mem, used_disk, used_cores;
1.1.11 by Soren Hansen
Import upstream version 1.6~bzr588
926
#define NC_MONIT_FILENAME "/var/run/eucalyptus/nc-stats"
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
927
928
	if (init())
929
		return 1;
930
931
	logprintfl(EUCADEBUG, "doDescribeInstances() invoked\n");
932
933
	if (nc_state.H->doDescribeInstances)
934
		ret = nc_state.H->doDescribeInstances (&nc_state, meta, instIds, instIdsLen, outInsts, outInstsLen);
935
	else 
936
		ret = nc_state.D->doDescribeInstances (&nc_state, meta, instIds, instIdsLen, outInsts, outInstsLen);
937
938
	if (ret)
939
		return ret;
940
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
941
942
	for (i=0; i < (*outInstsLen); i++) {
943
	  ncInstance *instance = (*outInsts)[i];
944
	  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);
945
	}
946
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
947
	/* allocate enough memory */
948
	len = (strlen(EUCALYPTUS_CONF_LOCATION) > strlen(NC_MONIT_FILENAME)) ? strlen(EUCALYPTUS_CONF_LOCATION) : strlen(NC_MONIT_FILENAME);
949
	len += 2 + strlen(nc_state.home);
950
	file_name = malloc(sizeof(char) * len);
951
	if (!file_name) {
952
		logprintfl(EUCAERROR, "Out of memory!\n");
953
		return ret;
954
	}
955
956
	sprintf(file_name, "%s/%s", nc_state.home, NC_MONIT_FILENAME);
957
	if (!strcmp(meta->userId, EUCALYPTUS_ADMIN)) {
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
958
		f = fopen(file_name, "w");
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
959
		if (!f) {
960
			f = fopen(file_name, "w+");
961
			if (!f)
962
				logprintfl(EUCAWARN, "Cannot create %s!\n", file_name);
963
			else {
964
				len = fileno(f);
965
				if (len > 0)
966
					fchmod(len, S_IRUSR|S_IWUSR);
967
			}
968
		}
969
		if (f) {
970
			int i;
971
			ncInstance * instance;
972
			char myName[CHAR_BUFFER_SIZE];
973
974
			fprintf(f, "version: %s\n", EUCA_VERSION);
975
			fprintf(f, "timestamp: %ld\n", time(NULL));
976
			if (gethostname(myName, CHAR_BUFFER_SIZE) == 0)
977
				fprintf(f, "node: %s\n", myName);
978
			fprintf(f, "hypervisor: %s\n", nc_state.H->name);
979
			fprintf(f, "network: %s\n", nc_state.vnetconfig->mode);
980
981
			used_disk = used_mem = used_cores = 0;
982
			for (i=0; i < (*outInstsLen); i++) {
983
				instance = (*outInsts)[i];
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
984
				used_disk += instance->params.disk;
985
				used_mem += instance->params.mem;
986
				used_cores += instance->params.cores;
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
987
			}
988
989
			fprintf(f, "memory (max/avail/used) MB: %lld/%lld/%lld\n", nc_state.mem_max, nc_state.mem_max - used_mem, used_mem);
990
			fprintf(f, "disk (max/avail/used) GB: %lld/%lld/%lld\n", nc_state.disk_max, nc_state.disk_max - used_disk, used_disk);
1.1.10 by Soren Hansen
Import upstream version 1.6~bzr515
991
			fprintf(f, "cores (max/avail/used): %lld/%lld/%lld\n", nc_state.cores_max, nc_state.cores_max - used_cores, used_cores);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
992
993
			for (i=0; i < (*outInstsLen); i++) {
994
				instance = (*outInsts)[i];
995
				fprintf(f, "id: %s", instance->instanceId);
996
				fprintf(f, " userId: %s", instance->userId);
997
				fprintf(f, " state: %s", instance->stateName);
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
998
				fprintf(f, " mem: %d", instance->params.mem);
999
				fprintf(f, " disk: %d", instance->params.disk);
1000
				fprintf(f, " cores: %d", instance->params.cores);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
1001
				fprintf(f, " private: %s", instance->ncnet.privateIp);
1002
				fprintf(f, " public: %s\n", instance->ncnet.publicIp);
1003
			}
1004
			fclose(f);
1005
		}
1006
	}
1007
	free(file_name);
1008
1009
	return ret;
1010
}
1011
1012
int doPowerDown(ncMetadata *meta) {
1013
	int ret;
1014
1015
	if (init())
1016
		return 1;
1017
1018
	logprintfl(EUCADEBUG, "doPowerDown() invoked\n");
1019
1020
	if (nc_state.H->doPowerDown) 
1021
		ret = nc_state.H->doPowerDown(&nc_state, meta);
1022
	else 
1023
		ret = nc_state.D->doPowerDown(&nc_state, meta);
1024
1025
	return ret;
1 by Soren Hansen
Import upstream version 1.5~bzr139
1026
}
1027
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
1028
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)
1 by Soren Hansen
Import upstream version 1.5~bzr139
1029
{
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
1030
	int ret;
1031
1032
	if (init())
1033
		return 1;
1034
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
1035
	logprintfl (EUCAINFO, "doRunInstance() invoked (id=%s cores=%d disk=%d memory=%d)\n", instanceId, params->cores, params->disk, params->mem);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
1036
	logprintfl (EUCAINFO, "                         image=%s at %s\n", imageId, imageURL);
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
1037
	if (kernelId && kernelURL)
1038
	  logprintfl (EUCAINFO, "                         krnel=%s at %s\n", kernelId, kernelURL);
1039
	if (ramdiskId && ramdiskURL)
1040
	  logprintfl (EUCAINFO, "                         rmdsk=%s at %s\n", ramdiskId, ramdiskURL);
1041
	logprintfl (EUCAINFO, "                         vlan=%d priMAC=%s privIp=%s\n", netparams->vlan, netparams->privateMac, netparams->privateIp);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
1042
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
1043
	int i;
1044
	for (i=0; i<EUCA_MAX_DEVMAPS; i++) {
1045
	  deviceMapping * dm = &(params->deviceMapping[i]);
1046
	  if (strlen(dm->deviceName)>0) {
1047
	    logprintfl (EUCAINFO, "                         device mapping: %s=%s size=%d format=%s\n", dm->deviceName, dm->virtualName, dm->size, dm->format);
1048
	  }
1049
	}
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
1050
1051
	if (nc_state.H->doRunInstance)
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
1052
 	  ret = nc_state.H->doRunInstance (&nc_state, meta, instanceId, reservationId, params, imageId, imageURL, kernelId, kernelURL, ramdiskId, ramdiskURL, keyName, netparams, userData, launchIndex, groupNames, groupNamesSize, outInst);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
1053
	else
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
1054
	  ret = nc_state.D->doRunInstance (&nc_state, meta, instanceId, reservationId, params, imageId, imageURL, kernelId, kernelURL, ramdiskId, ramdiskURL, keyName, netparams, userData, launchIndex, groupNames, groupNamesSize, outInst);
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
1055
1056
	return ret;
1 by Soren Hansen
Import upstream version 1.5~bzr139
1057
}
1058
1059
int doTerminateInstance (ncMetadata *meta, char *instanceId, int *shutdownState, int *previousState)
1060
{
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
1061
	int ret; 
1062
1063
	if (init())
1064
		return 1;
1065
1066
	logprintfl (EUCAINFO, "doTerminateInstance() invoked (id=%s)\n", instanceId);
1067
1068
	if (nc_state.H->doTerminateInstance) 
1069
		ret = nc_state.H->doTerminateInstance(&nc_state, meta, instanceId, shutdownState, previousState);
1070
	else 
1071
		ret = nc_state.D->doTerminateInstance(&nc_state, meta, instanceId, shutdownState, previousState);
1072
1073
	return ret;
1 by Soren Hansen
Import upstream version 1.5~bzr139
1074
}
1075
1076
int doRebootInstance (ncMetadata *meta, char *instanceId) 
1077
{
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
1078
	int ret;
1079
1080
	if (init())
1081
		return 1;
1082
		
1083
	logprintfl(EUCAINFO, "doRebootInstance() invoked  (id=%s)\n", instanceId);
1084
1085
	if (nc_state.H->doRebootInstance)
1086
		ret = nc_state.H->doRebootInstance (&nc_state, meta, instanceId);
1087
	else
1088
		ret = nc_state.D->doRebootInstance (&nc_state, meta, instanceId);
1089
1090
	return ret;
1 by Soren Hansen
Import upstream version 1.5~bzr139
1091
}
1092
1093
int doGetConsoleOutput (ncMetadata *meta, char *instanceId, char **consoleOutput) 
1094
{
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
1095
	int ret;
1096
1097
	if (init())
1098
		return 1;
1099
1100
	logprintfl (EUCAINFO, "doGetConsoleOutput() invoked (id=%s)\n", instanceId);
1101
1102
	if (nc_state.H->doGetConsoleOutput) 
1103
		ret = nc_state.H->doGetConsoleOutput (&nc_state, meta, instanceId, consoleOutput);
1104
	else
1105
		ret = nc_state.D->doGetConsoleOutput (&nc_state, meta, instanceId, consoleOutput);
1106
1107
	return ret;
1 by Soren Hansen
Import upstream version 1.5~bzr139
1108
}
1109
1110
int doDescribeResource (ncMetadata *meta, char *resourceType, ncResource **outRes)
1111
{
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
1112
	int ret;
1113
1114
	if (init())
1115
		return 1;
1116
1117
	logprintfl(EUCADEBUG, "doDescribeResource() invoked\n");
1118
1119
	if (nc_state.H->doDescribeResource)
1120
		ret = nc_state.H->doDescribeResource (&nc_state, meta, resourceType, outRes);
1121
	else 
1122
		ret = nc_state.D->doDescribeResource (&nc_state, meta, resourceType, outRes);
1123
1124
	return ret;
1 by Soren Hansen
Import upstream version 1.5~bzr139
1125
}
1126
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
1127
int
1128
doStartNetwork (	ncMetadata *ccMeta,
1129
			char **remoteHosts,
1130
			int remoteHostsLen,
1131
			int port,
1132
			int vlan)
1 by Soren Hansen
Import upstream version 1.5~bzr139
1133
{
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
1134
	int ret;
1135
1136
	if (init())
1137
		return 1;
1138
1139
	logprintfl(EUCADEBUG, "doStartNetwork() invoked\n");
1140
1141
	if (nc_state.H->doStartNetwork) 
1142
		ret = nc_state.H->doStartNetwork (&nc_state, ccMeta, remoteHosts, remoteHostsLen, port, vlan);
1143
	else 
1144
		ret = nc_state.D->doStartNetwork (&nc_state, ccMeta, remoteHosts, remoteHostsLen, port, vlan);
1145
	
1146
	return ret;
1 by Soren Hansen
Import upstream version 1.5~bzr139
1147
}
1148
1149
int doAttachVolume (ncMetadata *meta, char *instanceId, char *volumeId, char *remoteDev, char *localDev)
1150
{
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
1151
	int ret;
1152
1153
	if (init())
1154
		return 1;
1155
1156
	logprintfl (EUCAINFO, "doAttachVolume() invoked (id=%s vol=%s remote=%s local=%s)\n", instanceId, volumeId, remoteDev, localDev);
1157
1158
	if (nc_state.H->doAttachVolume)
1159
		ret = nc_state.H->doAttachVolume(&nc_state, meta, instanceId, volumeId, remoteDev, localDev);
1160
	else
1161
		ret = nc_state.D->doAttachVolume(&nc_state, meta, instanceId, volumeId, remoteDev, localDev);
1162
	
1163
	return ret;
1 by Soren Hansen
Import upstream version 1.5~bzr139
1164
}
1165
1166
int doDetachVolume (ncMetadata *meta, char *instanceId, char *volumeId, char *remoteDev, char *localDev, int force)
1167
{
1.1.9 by Soren Hansen
Import upstream version 1.6~bzr452
1168
	int ret;
1169
1170
	if (init())
1171
		return 1;
1172
1173
	logprintfl (EUCAINFO, "doDetachVolume() invoked (id=%s vol=%s remote=%s local=%s force=%d)\n", instanceId, volumeId, remoteDev, localDev, force);
1174
1175
	if (nc_state.H->doDetachVolume)
1176
		ret = nc_state.H->doDetachVolume (&nc_state, meta, instanceId, volumeId, remoteDev, localDev, force);
1177
	else 
1178
		ret = nc_state.D->doDetachVolume (&nc_state, meta, instanceId, volumeId, remoteDev, localDev, force);
1179
1180
	return ret;
1 by Soren Hansen
Import upstream version 1.5~bzr139
1181
}
1.1.25 by Dustin Kirkland
Import upstream version 1.6.2~bzr1103
1182
1183
int check_iscsi(char* dev_string) {
1184
    if(strchr(dev_string, ',') == NULL)
1185
	return 0;
1186
    return 1;
1187
}
1188
1189
void parse_target(char *dev_string) {
1190
    char *delimiter = ",";
1191
    char *brk, *part;
1192
    char dev_name[256];
1193
    snprintf(dev_name, 256, "%s", dev_string);
1194
1195
    for (part = strtok_r(dev_name, delimiter, &brk); part != NULL; part = strtok_r(NULL, delimiter, &brk)) {
1196
    }  
1197
}
1198
1199
char* connect_iscsi_target(const char *storage_cmd_path, char *dev_string) {
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
1200
    char buf [MAX_PATH];
1.1.25 by Dustin Kirkland
Import upstream version 1.6.2~bzr1103
1201
    char *retval;
1202
    
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
1203
    snprintf (buf, MAX_PATH, "%s %s", storage_cmd_path, dev_string);
1.1.25 by Dustin Kirkland
Import upstream version 1.6.2~bzr1103
1204
    logprintfl (EUCAINFO, "connect_iscsi_target invoked (dev_string=%s)\n", dev_string);
1205
    if ((retval = system_output(buf)) == NULL) {
1206
	logprintfl (EUCAERROR, "ERROR: connect_iscsi_target failed\n");
1207
    } else {
1208
	logprintfl (EUCAINFO, "Attached device: %s\n", retval);
1209
    } 
1210
    return retval;
1211
}
1212
1213
int disconnect_iscsi_target(const char *storage_cmd_path, char *dev_string) {
1214
    logprintfl (EUCAINFO, "disconnect_iscsi_target invoked (dev_string=%s)\n", dev_string);
1215
    if (vrun("%s %s", storage_cmd_path, dev_string) != 0) {
1216
	logprintfl (EUCAERROR, "ERROR: disconnect_iscsi_target failed\n");
1217
	return -1;
1218
    }
1219
    return 0;
1220
}
1221
1222
char* get_iscsi_target(const char *storage_cmd_path, char *dev_string) {
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
1223
    char buf [MAX_PATH];
1.1.25 by Dustin Kirkland
Import upstream version 1.6.2~bzr1103
1224
    char *retval;
1225
    
1.1.38 by Dave Walker (Daviey)
Import upstream version 2.0~bzr1211
1226
    snprintf (buf, MAX_PATH, "%s %s", storage_cmd_path, dev_string);
1.1.25 by Dustin Kirkland
Import upstream version 1.6.2~bzr1103
1227
    logprintfl (EUCAINFO, "get_iscsi_target invoked (dev_string=%s)\n", dev_string);
1228
    if ((retval = system_output(buf)) == NULL) {
1229
	logprintfl (EUCAERROR, "ERROR: get_iscsi_target failed\n");
1230
    } else {
1231
	logprintfl (EUCAINFO, "Device: %s\n", retval);
1232
    } 
1233
    return retval;
1234
}
1235