~ubuntu-core-dev/ubuntu/maverick/eucalyptus/devel

« back to all changes in this revision

Viewing changes to .pc/18-priv_security.patch/node/handlers_xen.c

  • Committer: Dustin Kirkland
  • Date: 2010-07-22 08:41:57 UTC
  • mfrom: (1050.1.19 ubuntu)
  • Revision ID: kirkland@x200-20100722084157-zh2p8dkawznvxxpn
Approving Dave Walker's merge of new upstream Eucalyptus 2.0 release.

Dustin Kirkland <kirkland@canonical.com>

* New major upstream version merge, 2.0 (r1211).
  - 01-wsdl-stubs.patch, debian/wsdl.md5sums: wsdl stubs updated.
  - 11-state-cleanup-memleakfix.patch: Removed, fixed upstream.
  - 21-eucalyptus-1.7-with-gwt-1.6.4.patch: New patch, allows 
    eucalyptus-1.7 to be built against gwt 1.6.4. Based on patch courtesy 
    of Dmitrii Zagorodnov, upstream. (LP: #597330)
* debian/eucalyptus-java-common.links: 
  - Changed symlink for groovy, point to groovy.all.jar, making compatiable 
    with groovy versions >1.7. (LP: #595421)
  - Added ant.jar & jetty-rewrite-handler.jar as they are now required.
* debian/control
  - & debian/build-jars: Added libjavassist-java and libjetty-extra-java as 
    build dependencies.
  - Added libjetty-extra-java as a dependency of eucalyptus-java-common
* The binary resulting jar's have been renamed from eucalyptus-*-1.6.2.jar
  to eucalyptus-*-main.jar:    
  - debian/eucalyptus-cc.upstart
  - debian/eucalyptus-cloud.install
  - debian/eucalyptus-common.eucalyptus.upstart
  - debian/eucalyptus-java-common.install
  - debian/eucalyptus-network.upstart
  - debian/eucalyptus-sc.install
  - debian/eucalyptus-walrus.install
* debian/eucalyptus-java-common.install: New upstream jars that have been
  installed:
  - eucalyptus-db-hsqldb-ext-main.jar
  - eucalyptus-component-main.jar
* debian/control:
  - Updated Standards Version to 3.8.4 (no change)
  - Updated the upstream Homepage to: http://open.eucalyptus.com/
  - Changed Vcs-Bzr to reflect new location of Ubuntu hosted development branch.
  - Made the Build Dependency of groovy and the binary eucalyptus-java-common
    package depend on version >=1.7.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
*/
 
60
#include <stdio.h>
 
61
#include <stdlib.h>
 
62
#define __USE_GNU /* strnlen */
 
63
#include <string.h> /* strlen, strcpy */
 
64
#include <time.h>
 
65
#include <sys/types.h> /* fork */
 
66
#include <sys/wait.h> /* waitpid */
 
67
#include <unistd.h>
 
68
#include <assert.h>
 
69
#include <errno.h>
 
70
#include <pthread.h>
 
71
#include <signal.h> /* SIGINT */
 
72
#include <sys/stat.h>
 
73
#include <fcntl.h>
 
74
 
 
75
#include "ipc.h"
 
76
#include "misc.h"
 
77
#include <handlers.h>
 
78
#include <storage.h>
 
79
#include <eucalyptus.h>
 
80
#include <euca_auth.h>
 
81
 
 
82
/* coming from handlers.c */
 
83
extern sem * hyp_sem;
 
84
extern sem * inst_sem;
 
85
extern bunchOfInstances * global_instances;
 
86
 
 
87
#define HYPERVISOR_URI "xen:///"
 
88
 
 
89
static int doInitialize (struct nc_state_t *nc) 
 
90
{
 
91
        char *s = NULL;
 
92
        virNodeInfo ni;
 
93
        long long dom0_min_mem;
 
94
 
 
95
        logprintfl(EUCADEBUG, "doInitialized() invoked\n");
 
96
 
 
97
        /* set up paths of Eucalyptus commands NC relies on */
 
98
        snprintf (nc->gen_libvirt_cmd_path, MAX_PATH, EUCALYPTUS_GEN_LIBVIRT_XML, nc->home, nc->home);
 
99
        snprintf (nc->get_info_cmd_path, MAX_PATH, EUCALYPTUS_GET_XEN_INFO, nc->home, nc->home);
 
100
        snprintf (nc->virsh_cmd_path, MAX_PATH, EUCALYPTUS_VIRSH, nc->home);
 
101
        snprintf (nc->xm_cmd_path, MAX_PATH, EUCALYPTUS_XM);
 
102
        snprintf (nc->detach_cmd_path, MAX_PATH, EUCALYPTUS_DETACH, nc->home, nc->home);
 
103
        snprintf (nc->connect_storage_cmd_path, MAX_PATH, EUCALYPTUS_CONNECT_ISCSI, nc->home);
 
104
        snprintf (nc->disconnect_storage_cmd_path, MAX_PATH, EUCALYPTUS_DISCONNECT_ISCSI, nc->home);
 
105
        snprintf (nc->get_storage_cmd_path, MAX_PATH, EUCALYPTUS_GET_ISCSI, nc->home);
 
106
        strcpy(nc->uri, HYPERVISOR_URI);
 
107
        nc->convert_to_disk = 0;
 
108
 
 
109
        /* check connection is fresh */
 
110
        if (!check_hypervisor_conn()) {
 
111
          return ERROR_FATAL;
 
112
        }
 
113
 
 
114
        /* get resources */
 
115
        if (virNodeGetInfo(nc->conn, &ni)) {
 
116
                logprintfl (EUCAFATAL, "error: failed to discover resources\n");
 
117
                return ERROR_FATAL;
 
118
        }
 
119
 
 
120
        /* dom0-min-mem has to come from xend config file */
 
121
        s = system_output (nc->get_info_cmd_path);
 
122
        if (get_value (s, "dom0-min-mem", &dom0_min_mem)) {
 
123
                logprintfl (EUCAFATAL, "error: did not find dom0-min-mem in output from %s\n", nc->get_info_cmd_path);
 
124
                free (s);
 
125
                return ERROR_FATAL;
 
126
        }
 
127
        free (s);
 
128
 
 
129
        /* calculate the available memory */
 
130
        nc->mem_max = ni.memory/1024 - 32 - dom0_min_mem;
 
131
 
 
132
        /* calculate the available cores */
 
133
        nc->cores_max = ni.cpus;
 
134
 
 
135
        /* let's adjust the values based on the config values */
 
136
        if (nc->config_max_mem && nc->config_max_mem < nc->mem_max)
 
137
                nc->mem_max = nc->config_max_mem;
 
138
        if (nc->config_max_cores)
 
139
                nc->cores_max = nc->config_max_cores;
 
140
 
 
141
        logprintfl(EUCAINFO, "Using %lld cores\n", nc->cores_max);
 
142
        logprintfl(EUCAINFO, "Using %lld memory\n", nc->mem_max);
 
143
 
 
144
        return OK;
 
145
}
 
146
 
 
147
static int
 
148
doRunInstance(          struct nc_state_t *nc,
 
149
                        ncMetadata *meta,
 
150
                        char *instanceId,
 
151
                        char *reservationId,
 
152
                        virtualMachine *params, 
 
153
                        char *imageId, char *imageURL, 
 
154
                        char *kernelId, char *kernelURL, 
 
155
                        char *ramdiskId, char *ramdiskURL, 
 
156
                        char *keyName, 
 
157
                        //                      char *privMac, char *privIp, int vlan, 
 
158
                        netConfig *netparams,
 
159
                        char *userData, char *launchIndex,
 
160
                        char **groupNames, int groupNamesSize,
 
161
                        ncInstance **outInst)
 
162
{
 
163
    ncInstance * instance = NULL;
 
164
    * outInst = NULL;
 
165
    pid_t pid;
 
166
    netConfig ncnet;
 
167
    int error;
 
168
 
 
169
    memcpy(&ncnet, netparams, sizeof(netConfig));
 
170
 
 
171
    /* check as much as possible before forking off and returning */
 
172
    sem_p (inst_sem);
 
173
    instance = find_instance (&global_instances, instanceId);
 
174
    sem_v (inst_sem);
 
175
    if (instance) {
 
176
        logprintfl (EUCAFATAL, "Error: instance %s already running\n", instanceId);
 
177
        return 1; /* TODO: return meaningful error codes? */
 
178
    }
 
179
    if (!(instance = allocate_instance (instanceId, 
 
180
                                        reservationId,
 
181
                                        params, 
 
182
                                        imageId, imageURL,
 
183
                                        kernelId, kernelURL,
 
184
                                        ramdiskId, ramdiskURL,
 
185
                                        instance_state_names[PENDING], 
 
186
                                        PENDING, 
 
187
                                        meta->userId, 
 
188
                                        &ncnet, keyName,
 
189
                                        userData, launchIndex, groupNames, groupNamesSize))) {
 
190
        logprintfl (EUCAFATAL, "Error: could not allocate instance struct\n");
 
191
        return 2;
 
192
    }
 
193
    change_state(instance, STAGING);
 
194
 
 
195
    sem_p (inst_sem); 
 
196
    error = add_instance (&global_instances, instance);
 
197
    sem_v (inst_sem);
 
198
    if ( error ) {
 
199
        free_instance (&instance);
 
200
        logprintfl (EUCAFATAL, "Error: could not save instance struct\n");
 
201
        return error;
 
202
    }
 
203
 
 
204
    instance->launchTime = time (NULL);
 
205
    /*
 
206
      instance->params.mem = params->mem;
 
207
      instance->params.cores = params->cores;
 
208
      instance->params.disk = params->disk;
 
209
      strcpy (instance->ncnet.privateIp, "0.0.0.0");
 
210
      strcpy (instance->ncnet.publicIp, "0.0.0.0");
 
211
    */
 
212
 
 
213
    /* do the potentially long tasks in a thread */
 
214
    pthread_attr_t* attr = (pthread_attr_t*) malloc(sizeof(pthread_attr_t));
 
215
    if (!attr) { 
 
216
        free_instance (&instance);
 
217
        logprintfl (EUCAFATAL, "Warning: out of memory\n");
 
218
        return 1;
 
219
    }
 
220
    pthread_attr_init(attr);
 
221
    pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED);
 
222
    
 
223
    if ( pthread_create (&(instance->tcb), attr, startup_thread, (void *)instance) ) {
 
224
        pthread_attr_destroy(attr);
 
225
        logprintfl (EUCAFATAL, "failed to spawn a VM startup thread\n");
 
226
        sem_p (inst_sem);
 
227
        remove_instance (&global_instances, instance);
 
228
        sem_v (inst_sem);
 
229
        free_instance (&instance);
 
230
        if (attr) free(attr);
 
231
        return 1;
 
232
    }
 
233
    pthread_attr_destroy(attr);
 
234
    if (attr) free(attr);
 
235
 
 
236
    * outInst = instance;
 
237
    return 0;
 
238
 
 
239
}
 
240
 
 
241
static int doRebootInstance(    struct nc_state_t *nc,
 
242
                                ncMetadata *meta,
 
243
                                char *instanceId) 
 
244
{
 
245
    ncInstance *instance;
 
246
    virConnectPtr *conn;
 
247
 
 
248
    sem_p (inst_sem); 
 
249
    instance = find_instance(&global_instances, instanceId);
 
250
    sem_v (inst_sem);
 
251
    if ( instance == NULL ) return NOT_FOUND;
 
252
    
 
253
    /* reboot the Xen domain */
 
254
    conn = check_hypervisor_conn();
 
255
    if (conn) {
 
256
        sem_p(hyp_sem);
 
257
        virDomainPtr dom = virDomainLookupByName(*conn, instanceId);
 
258
        sem_v(hyp_sem);
 
259
        if (dom) {
 
260
            /* also protect 'reboot', just in case */
 
261
            sem_p (hyp_sem);
 
262
            int err=virDomainReboot (dom, 0);
 
263
            sem_v (hyp_sem);
 
264
            if (err==0) {
 
265
                logprintfl (EUCAINFO, "rebooting Xen domain for instance %s\n", instanceId);
 
266
            }
 
267
            sem_p(hyp_sem);
 
268
            virDomainFree(dom); /* necessary? */
 
269
            sem_v(hyp_sem);
 
270
        } else {
 
271
            if (instance->state != BOOTING && instance->state != STAGING) {
 
272
                logprintfl (EUCAWARN, "warning: domain %s to be rebooted not running on hypervisor\n", instanceId);
 
273
            }
 
274
        }
 
275
    }
 
276
 
 
277
    return 0;
 
278
}
 
279
 
 
280
static int
 
281
doGetConsoleOutput(     struct nc_state_t *nc,
 
282
                        ncMetadata *meta,
 
283
                        char *instanceId,
 
284
                        char **consoleOutput) {
 
285
 
 
286
  char *console_output=NULL, *console_append=NULL, *console_main=NULL;
 
287
  char console_file[MAX_PATH];
 
288
  int rc, fd, ret;
 
289
  struct stat statbuf;
 
290
 
 
291
  int bufsize, pid, status;
 
292
 
 
293
  *consoleOutput = NULL;
 
294
 
 
295
  snprintf(console_file, 1024, "%s/%s/%s/console.append.log", scGetInstancePath(), meta->userId, instanceId);
 
296
  rc = stat(console_file, &statbuf);
 
297
  if (rc >= 0) {
 
298
    fd = open(console_file, O_RDONLY);
 
299
    if (fd >= 0) {
 
300
      console_append = malloc(4096);
 
301
      if (console_append) {
 
302
        bzero(console_append, 4096);
 
303
        rc = read(fd, console_append, (4096)-1);
 
304
        close(fd);          
 
305
      }
 
306
    }
 
307
  }
 
308
 
 
309
 
 
310
  if (getuid() != 0) {
 
311
    console_main = strdup("NOT SUPPORTED");
 
312
    if (!console_main) {
 
313
      fprintf(stderr, "strdup failed (out of memory?)\n");
 
314
      if (console_append) free(console_append);
 
315
      return 1;
 
316
    }
 
317
  } else {
 
318
 
 
319
  bufsize = sizeof(char) * 1024 * 64;
 
320
  console_main = malloc(bufsize);
 
321
  if (!console_main) {
 
322
    logprintfl(EUCAERROR, "doGetConsoleOutput(): out of memory!\n");
 
323
    if (console_append) free(console_append);
 
324
    return(1);
 
325
  }
 
326
  bzero(console_main, bufsize);
 
327
 
 
328
  snprintf(console_file, MAX_PATH, "/tmp/consoleOutput.%s", instanceId);
 
329
  
 
330
  pid = fork();
 
331
  if (pid == 0) {
 
332
    int fd;
 
333
    fd = open(console_file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
 
334
    if (fd < 0) {
 
335
      // error
 
336
    } else {
 
337
      dup2(fd, 2);
 
338
      dup2(2, 1);
 
339
      close(0);
 
340
      // TODO: test virsh console:
 
341
      // rc = execl(rootwrap_command_path, rootwrap_command_path, "virsh", "console", instanceId, NULL);
 
342
      rc = execl("/usr/sbin/xm", "/usr/sbin/xm", "console", instanceId, NULL);
 
343
      fprintf(stderr, "execl() failed\n");
 
344
      close(fd);
 
345
    }
 
346
    exit(0);
 
347
  } else {
 
348
    int count;
 
349
    fd_set rfds;
 
350
    struct timeval tv;
 
351
    struct stat statbuf;
 
352
    
 
353
    count=0;
 
354
    while(count < 10000 && stat(console_file, &statbuf) < 0) {count++;}
 
355
    fd = open(console_file, O_RDONLY);
 
356
    if (fd < 0) {
 
357
      logprintfl (EUCAERROR, "ERROR: could not open consoleOutput file %s for reading\n", console_file);
 
358
    } else {
 
359
      FD_ZERO(&rfds);
 
360
      FD_SET(fd, &rfds);
 
361
      tv.tv_sec = 0;
 
362
      tv.tv_usec = 500000;
 
363
      rc = select(1, &rfds, NULL, NULL, &tv);
 
364
      bzero(console_main, bufsize);
 
365
      
 
366
      count = 0;
 
367
      rc = 1;
 
368
      while(rc && count < 1000) {
 
369
        rc = read(fd, console_main, bufsize-1);
 
370
        count++;
 
371
      }
 
372
      close(fd);
 
373
    }
 
374
    kill(pid, 9);
 
375
    wait(&status);
 
376
  }
 
377
  
 
378
  unlink(console_file);
 
379
  }
 
380
  
 
381
  ret = 1;
 
382
  console_output = malloc( (64*1024) + 4096 );
 
383
  if (console_output) {
 
384
    bzero(console_output, (64*1024) + 4096 );
 
385
    if (console_append) {
 
386
      strncat(console_output, console_append, 4096);
 
387
    }
 
388
    if (console_main) {
 
389
      strncat(console_output, console_main, 1024*64);
 
390
    }
 
391
    *consoleOutput = base64_enc((unsigned char *)console_output, strlen(console_output));
 
392
    ret = 0;
 
393
  }
 
394
 
 
395
  if (console_append) free(console_append);
 
396
  if (console_main) free(console_main);
 
397
  if (console_output) free(console_output);
 
398
 
 
399
  return(ret);
 
400
}
 
401
 
 
402
static int
 
403
doAttachVolume (        struct nc_state_t *nc,
 
404
                        ncMetadata *meta,
 
405
                        char *instanceId,
 
406
                        char *volumeId,
 
407
                        char *remoteDev,
 
408
                        char *localDev)
 
409
{
 
410
    int ret = OK, rc;
 
411
    ncInstance * instance;
 
412
    char localDevReal[32];
 
413
    virConnectPtr *conn;
 
414
    struct stat statbuf;
 
415
 
 
416
    // fix up format of incoming local dev name, if we need to
 
417
    ret = convert_dev_names (localDev, localDevReal, NULL);
 
418
    if (ret)
 
419
        return ret;
 
420
 
 
421
    sem_p (inst_sem); 
 
422
    instance = find_instance(&global_instances, instanceId);
 
423
    sem_v (inst_sem);
 
424
    if ( instance == NULL ) 
 
425
        return NOT_FOUND;
 
426
 
 
427
    /* try attaching to the Xen domain */
 
428
    conn = check_hypervisor_conn();
 
429
    if (conn) {
 
430
        sem_p(hyp_sem);
 
431
        virDomainPtr dom = virDomainLookupByName(*conn, instanceId);
 
432
        sem_v(hyp_sem);
 
433
        if (dom) {
 
434
 
 
435
            int err = 0;
 
436
            char xml [1024];
 
437
            int is_iscsi_target = 0;
 
438
            char *local_iscsi_dev;
 
439
            rc = 0;
 
440
            if(check_iscsi(remoteDev)) {
 
441
                is_iscsi_target = 1;
 
442
                /*get credentials, decrypt them*/
 
443
                //parse_target(remoteDev);
 
444
                /*login to target*/
 
445
                local_iscsi_dev = connect_iscsi_target(nc->connect_storage_cmd_path, remoteDev);
 
446
                if (!local_iscsi_dev || !strstr(local_iscsi_dev, "/dev")) {
 
447
                  logprintfl(EUCAERROR, "AttachVolume(): failed to connect to iscsi target\n");
 
448
                  rc = 1;
 
449
                } else {
 
450
                  snprintf (xml, 1024, "<disk type='block'><driver name='phy'/><source dev='%s'/><target dev='%s'/></disk>", local_iscsi_dev, localDevReal);
 
451
                }
 
452
            } else {
 
453
                snprintf (xml, 1024, "<disk type='block'><driver name='phy'/><source dev='%s'/><target dev='%s'/></disk>", remoteDev, localDevReal);
 
454
                rc = stat(remoteDev, &statbuf);
 
455
                if (rc) {
 
456
                   logprintfl(EUCAERROR, "AttachVolume(): cannot locate local block device file '%s'\n", remoteDev);
 
457
                   rc = 1;
 
458
                }
 
459
            }
 
460
            if (!rc) {
 
461
                /* protect Xen calls, just in case */
 
462
                sem_p (hyp_sem);
 
463
                err = virDomainAttachDevice (dom, xml);
 
464
                sem_v (hyp_sem);
 
465
                if (err) {
 
466
                   logprintfl (EUCAERROR, "AttachVolume() failed (err=%d) XML=%s\n", err, xml);
 
467
//                   rc = doDetachVolume(nc, meta, instanceId, volumeId, remoteDev, localDev, 1);
 
468
                   ret = ERROR;
 
469
                } else {
 
470
                   logprintfl (EUCAINFO, "attached %s to %s in domain %s\n", remoteDev, localDevReal, instanceId);
 
471
                }
 
472
            } else { 
 
473
                ret = ERROR;
 
474
            }
 
475
 
 
476
            sem_p(hyp_sem);
 
477
            virDomainFree(dom);
 
478
            sem_v(hyp_sem);
 
479
            if(is_iscsi_target) {
 
480
              if (local_iscsi_dev) free(local_iscsi_dev);
 
481
            }
 
482
        } else {
 
483
            if (instance->state != BOOTING && instance->state != STAGING) {
 
484
                logprintfl (EUCAWARN, "warning: domain %s not running on hypervisor, cannot attach device\n", instanceId);
 
485
            }
 
486
            ret = ERROR;
 
487
        }
 
488
    } else {
 
489
        ret = ERROR;
 
490
    }
 
491
 
 
492
    if (ret==OK) {
 
493
        ncVolume * volume;
 
494
 
 
495
        sem_p (inst_sem);
 
496
        volume = add_volume (instance, volumeId, remoteDev, localDevReal, localDevReal, "attached");
 
497
        scSaveInstanceInfo(instance); /* to enable NC recovery */
 
498
        sem_v (inst_sem);
 
499
        if ( volume == NULL ) {
 
500
            logprintfl (EUCAFATAL, "ERROR: Failed to save the volume record, aborting volume attachment\n");
 
501
            return ERROR;
 
502
        }
 
503
    }
 
504
 
 
505
    return ret;
 
506
}
 
507
 
 
508
static int
 
509
doDetachVolume (        struct nc_state_t *nc,
 
510
                        ncMetadata *meta,
 
511
                        char *instanceId,
 
512
                        char *volumeId,
 
513
                        char *remoteDev,
 
514
                        char *localDev,
 
515
                        int force)
 
516
{
 
517
    int ret = OK;
 
518
    ncInstance * instance;
 
519
    char localDevReal[32];
 
520
    virConnectPtr *conn;
 
521
 
 
522
    // fix up format of incoming local dev name, if we need to
 
523
    ret = convert_dev_names (localDev, localDevReal, NULL);
 
524
    if (ret)
 
525
        return ret;
 
526
 
 
527
    sem_p (inst_sem); 
 
528
    instance = find_instance(&global_instances, instanceId);
 
529
    sem_v (inst_sem);
 
530
    if ( instance == NULL ) 
 
531
        return NOT_FOUND;
 
532
 
 
533
    /* try attaching to the Xen domain */
 
534
    conn = check_hypervisor_conn(); 
 
535
    if (conn) {
 
536
        sem_p(hyp_sem);
 
537
        virDomainPtr dom = virDomainLookupByName(*conn, instanceId);
 
538
        sem_v(hyp_sem);
 
539
        if (dom) {
 
540
            int err = 0, fd, rc, pid, status;
 
541
            char xml [1024], tmpfile[32], cmd[MAX_PATH];
 
542
            FILE *FH;
 
543
                    int is_iscsi_target = 0;
 
544
            char *local_iscsi_dev;
 
545
            if(check_iscsi(remoteDev)) {
 
546
                is_iscsi_target = 1;
 
547
                /*get credentials, decrypt them*/
 
548
                //parse_target(remoteDev);
 
549
                /*logout from target*/
 
550
                if((local_iscsi_dev = get_iscsi_target(nc->get_storage_cmd_path, remoteDev)) == NULL)
 
551
                    return ERROR;
 
552
                snprintf (xml, 1024, "<disk type='block'><driver name='phy'/><source dev='%s'/><target dev='%s'/></disk>", local_iscsi_dev, localDevReal);
 
553
            } else {
 
554
                snprintf (xml, 1024, "<disk type='block'><driver name='phy'/><source dev='%s'/><target dev='%s'/></disk>", remoteDev, localDevReal);
 
555
            }
 
556
            /* protect Xen calls, just in case */
 
557
            sem_p (hyp_sem);
 
558
            pid = fork();
 
559
            if (!pid) {
 
560
              char cmd[MAX_PATH];
 
561
              snprintf(tmpfile, 32, "/tmp/detachxml.XXXXXX");
 
562
              fd = mkstemp(tmpfile);
 
563
              if (fd > 0) {
 
564
                write(fd, xml, strlen(xml));
 
565
                close(fd);
 
566
                snprintf(cmd, MAX_PATH, "%s %s `which virsh` %s %s %s", nc->detach_cmd_path, nc->rootwrap_cmd_path, instanceId, localDevReal, tmpfile);
 
567
                rc = system(cmd);
 
568
                rc = rc>>8;
 
569
                unlink(tmpfile);
 
570
              } else {
 
571
                logprintfl(EUCAERROR, "could not write to tmpfile for detach XML: %s\n", tmpfile);
 
572
                rc = 1;
 
573
              } 
 
574
              exit(rc);
 
575
            } else {
 
576
              rc = timewait(pid, &status, 15);
 
577
              if (WEXITSTATUS(status)) {
 
578
                logprintfl(EUCAERROR, "failed to sucessfully run detach helper\n");
 
579
                err = 1;
 
580
              } else {
 
581
                err = 0;
 
582
              }
 
583
            }
 
584
#if 0
 
585
            if (!getuid()) {
 
586
              sem_p(hyp_sem);
 
587
              err = virDomainDetachDevice (dom, xml);
 
588
              sem_v(hyp_sem);
 
589
            } else {
 
590
              
 
591
              /* virsh detach function does not work as non-root user on xen (bug). workaround is to shellout to virsh */
 
592
              snprintf(tmpfile, 32, "/tmp/detachxml.XXXXXX");
 
593
              fd = mkstemp(tmpfile);
 
594
              if (fd > 0) {
 
595
                write(fd, xml, strlen(xml));
 
596
                close(fd);
 
597
                snprintf(cmd, MAX_PATH, "%s detach-device %s %s",virsh_command_path, instanceId, tmpfile);
 
598
                logprintfl(EUCADEBUG, "Running command: %s\n", cmd);
 
599
                err = WEXITSTATUS(system(cmd));
 
600
                unlink(tmpfile);
 
601
                if (err) {
 
602
                  logprintfl(EUCADEBUG, "first workaround command failed (%d), trying second workaround...\n", err);
 
603
                  snprintf(cmd, MAX_PATH, "%s block-detach %s %s", xm_command_path, instanceId, localDevReal);
 
604
                  logprintfl(EUCADEBUG, "Running command: %s\n", cmd);
 
605
                  err = WEXITSTATUS(system(cmd));
 
606
                }
 
607
              } else {
 
608
                err = 1;
 
609
              }
 
610
            }
 
611
#endif
 
612
            sem_v (hyp_sem);
 
613
            
 
614
            if (err) {
 
615
                logprintfl (EUCAERROR, "DetachVolume() failed (err=%d) XML=%s\n", err, xml);
 
616
                ret = ERROR;
 
617
            } else {
 
618
                logprintfl (EUCAINFO, "detached %s as %s in domain %s\n", remoteDev, localDevReal, instanceId);
 
619
            }
 
620
            sem_p(hyp_sem);
 
621
            virDomainFree(dom);
 
622
            sem_v(hyp_sem);
 
623
            if(is_iscsi_target) {
 
624
                if(disconnect_iscsi_target(nc->disconnect_storage_cmd_path, remoteDev) != 0) {
 
625
                    logprintfl (EUCAERROR, "disconnect_iscsi_target failed for %s\n", remoteDev);
 
626
                    ret = ERROR;
 
627
                }
 
628
                free(local_iscsi_dev);
 
629
            }
 
630
        } else {
 
631
            if (instance->state != BOOTING && instance->state != STAGING) {
 
632
                logprintfl (EUCAWARN, "warning: domain %s not running on hypervisor, cannot detach device\n", instanceId);
 
633
            }
 
634
            ret = ERROR;
 
635
        }
 
636
    } else {
 
637
        ret = ERROR;
 
638
    }
 
639
 
 
640
    if (ret==OK) {
 
641
        ncVolume * volume;
 
642
 
 
643
        sem_p (inst_sem);
 
644
        volume = free_volume (instance, volumeId, remoteDev, localDevReal);
 
645
        sem_v (inst_sem);
 
646
        if ( volume == NULL ) {
 
647
            logprintfl (EUCAFATAL, "ERROR: Failed to find and remove volume record, aborting volume detachment\n");
 
648
            return ERROR;
 
649
        }
 
650
    }
 
651
 
 
652
    return ret;
 
653
}
 
654
 
 
655
struct handlers xen_libvirt_handlers = {
 
656
    .name = "xen",
 
657
    .doInitialize        = doInitialize,
 
658
    .doDescribeInstances = NULL,
 
659
    .doRunInstance       = doRunInstance,
 
660
    .doTerminateInstance = NULL,
 
661
    .doRebootInstance    = doRebootInstance,
 
662
    .doGetConsoleOutput  = doGetConsoleOutput,
 
663
    .doDescribeResource  = NULL,
 
664
    .doStartNetwork      = NULL,
 
665
    .doPowerDown         = NULL,
 
666
    .doAttachVolume      = doAttachVolume,
 
667
    .doDetachVolume      = doDetachVolume
 
668
};
 
669