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

« back to all changes in this revision

Viewing changes to .pc/07-local_support_euca_conf-in.patch/cluster/handlers.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
#include <sys/types.h>
 
63
#include <unistd.h>
 
64
#include <sys/wait.h>
 
65
#include <sys/mman.h>
 
66
#include <semaphore.h>
 
67
#include <netdb.h>
 
68
#include <sys/socket.h>
 
69
#include <netinet/in.h>
 
70
#include <arpa/inet.h>
 
71
#include <signal.h>
 
72
 
 
73
#include "axis2_skel_EucalyptusCC.h"
 
74
 
 
75
#include <server-marshal.h>
 
76
#include <handlers.h>
 
77
#include <storage.h>
 
78
#include <vnetwork.h>
 
79
#include <misc.h>
 
80
#include <ipc.h>
 
81
 
 
82
#include <euca_axis.h>
 
83
#include "data.h"
 
84
#include "client-marshal.h"
 
85
 
 
86
#include <euca_auth.h>
 
87
 
 
88
#define SUPERUSER "eucalyptus"
 
89
 
 
90
// local globals
 
91
int config_init=0;
 
92
int local_init=0;
 
93
int thread_init=0;
 
94
int init=0;
 
95
 
 
96
// to be stored in shared memory
 
97
ccConfig *config=NULL;
 
98
 
 
99
ccInstanceCache *instanceCache=NULL;
 
100
 
 
101
ccResourceCache *resourceCache=NULL;
 
102
 
 
103
vnetConfig *vnetconfig=NULL;
 
104
 
 
105
sem_t *locks[ENDLOCK] = {NULL, NULL, NULL, NULL, NULL, NULL};
 
106
int mylocks[ENDLOCK] = {0,0,0,0,0,0};
 
107
 
 
108
int ncClientCall(ncMetadata *meta, int timeout, int ncLock, char *ncURL, char *ncOp, ...) {
 
109
  va_list al;
 
110
  int pid, rc=0, ret=0, status=0, opFail=0, len, rbytes, i;
 
111
  int filedes[2];
 
112
 
 
113
  logprintfl(EUCADEBUG, "ncClientCall(%s): called ncURL=%s timeout=%d\n", ncOp, ncURL, timeout);
 
114
  
 
115
  rc = pipe(filedes);
 
116
  if (rc) {
 
117
    logprintfl(EUCAERROR, "ncClientCall(%s): cannot create pipe\n", ncOp);
 
118
    return(1);
 
119
  }
 
120
 
 
121
  va_start(al, ncOp);
 
122
 
 
123
  // grab the lock
 
124
  sem_mywait(ncLock);
 
125
  
 
126
  pid = fork();
 
127
  if (!pid) {
 
128
    ncStub *ncs;
 
129
 
 
130
    close(filedes[0]);
 
131
    ncs = ncStubCreate(ncURL, NULL, NULL);
 
132
    if (config->use_wssec) {
 
133
      rc = InitWSSEC(ncs->env, ncs->stub, config->policyFile);
 
134
    }
 
135
              
 
136
    logprintfl(EUCADEBUG, "\tncClientCall(%s): ppid=%d client calling '%s'\n", ncOp, getppid(), ncOp);
 
137
    if (!strcmp(ncOp, "ncGetConsoleOutput")) {
 
138
      // args: char *instId
 
139
      char *instId = va_arg(al, char *);
 
140
      char **consoleOutput=va_arg(al, char **);
 
141
 
 
142
      rc = ncGetConsoleOutputStub(ncs, meta, instId, consoleOutput);
 
143
      if (timeout && consoleOutput) {
 
144
        if (!rc && *consoleOutput) {
 
145
          len = strlen(*consoleOutput) + 1;
 
146
          rc = write(filedes[1], &len, sizeof(int));
 
147
          rc = write(filedes[1], *consoleOutput, sizeof(char) * len);
 
148
          rc = 0;
 
149
        } else {
 
150
          len = 0;
 
151
          rc = write(filedes[1], &len, sizeof(int));
 
152
          rc = 1;
 
153
        }
 
154
      }
 
155
    } else if (!strcmp(ncOp, "ncAttachVolume")) {
 
156
      char *instanceId = va_arg(al, char *);
 
157
      char *volumeId = va_arg(al, char *);      
 
158
      char *remoteDev = va_arg(al, char *);      
 
159
      char *localDev = va_arg(al, char *);      
 
160
 
 
161
      rc = ncAttachVolumeStub(ncs, meta, instanceId, volumeId, remoteDev, localDev);
 
162
    } else if (!strcmp(ncOp, "ncDetachVolume")) {
 
163
      char *instanceId = va_arg(al, char *);
 
164
      char *volumeId = va_arg(al, char *);      
 
165
      char *remoteDev = va_arg(al, char *);      
 
166
      char *localDev = va_arg(al, char *);      
 
167
      int force = va_arg(al, int);
 
168
 
 
169
      rc = ncDetachVolumeStub(ncs, meta, instanceId, volumeId, remoteDev, localDev, force);
 
170
    } else if (!strcmp(ncOp, "ncPowerDown")) {
 
171
      rc = ncPowerDownStub(ncs, meta);
 
172
    } else if (!strcmp(ncOp, "ncRebootInstance")) {
 
173
      char *instId = va_arg(al, char *);
 
174
 
 
175
      rc = ncRebootInstanceStub(ncs, meta, instId);
 
176
    } else if (!strcmp(ncOp, "ncTerminateInstance")) {
 
177
      char *instId = va_arg(al, char *);
 
178
      int *shutdownState = va_arg(al, int *);
 
179
      int *previousState = va_arg(al, int *);
 
180
      
 
181
      rc = ncTerminateInstanceStub(ncs, meta, instId, shutdownState, previousState);
 
182
      if (timeout) {
 
183
        if (!rc) {
 
184
          len = 2;
 
185
          rc = write(filedes[1], &len, sizeof(int));
 
186
          rc = write(filedes[1], shutdownState, sizeof(int));
 
187
          rc = write(filedes[1], previousState, sizeof(int));
 
188
          rc = 0;
 
189
        } else {
 
190
          len = 0;
 
191
          rc = write(filedes[1], &len, sizeof(int));
 
192
          rc = 1;
 
193
        }
 
194
      }
 
195
    } else if (!strcmp(ncOp, "ncStartNetwork")) {
 
196
      char **peers = va_arg(al, char **);
 
197
      int peersLen = va_arg(al, int);
 
198
      int port = va_arg(al, int);
 
199
      int vlan = va_arg(al, int);
 
200
      char **outStatus = va_arg(al, char **);
 
201
      
 
202
      rc = ncStartNetworkStub(ncs, meta, peers, peersLen, port, vlan, outStatus);
 
203
      if (timeout && outStatus) {
 
204
        if (!rc && *outStatus) {
 
205
          len = strlen(*outStatus) + 1;
 
206
          rc = write(filedes[1], &len, sizeof(int));
 
207
          rc = write(filedes[1], *outStatus, sizeof(char) * len);
 
208
          rc = 0;
 
209
        } else {
 
210
          len = 0;
 
211
          rc = write(filedes[1], &len, sizeof(int));
 
212
          rc = 1;
 
213
        }      
 
214
      }
 
215
    } else if (!strcmp(ncOp, "ncRunInstance")) {
 
216
      char *instId = va_arg(al, char *);
 
217
      char *reservationId = va_arg(al, char *);
 
218
      virtualMachine *ncvm = va_arg(al, virtualMachine *);
 
219
      char *imageId = va_arg(al, char *);
 
220
      char *imageURL = va_arg(al, char *);
 
221
      char *kernelId = va_arg(al, char *);
 
222
      char *kernelURL = va_arg(al, char *);
 
223
      char *ramdiskId = va_arg(al, char *);
 
224
      char *ramdiskURL = va_arg(al, char *);
 
225
      char *keyName = va_arg(al, char *);
 
226
      netConfig *ncnet = va_arg(al, netConfig *);
 
227
      char *userData = va_arg(al, char *);
 
228
      char *launchIndex = va_arg(al, char *);
 
229
      char **netNames = va_arg(al, char **);
 
230
      int netNamesLen = va_arg(al, int);
 
231
      ncInstance **outInst = va_arg(al, ncInstance **);
 
232
      
 
233
      rc = ncRunInstanceStub(ncs, meta, instId, reservationId, ncvm, imageId, imageURL, kernelId, kernelURL, ramdiskId, ramdiskURL, keyName, ncnet, userData, launchIndex, netNames, netNamesLen, outInst);
 
234
      if (timeout && outInst) {
 
235
        if (!rc && *outInst) {
 
236
          len = sizeof(ncInstance);
 
237
          rc = write(filedes[1], &len, sizeof(int));
 
238
          rc = write(filedes[1], *outInst, sizeof(ncInstance));
 
239
          rc = 0;
 
240
        } else {
 
241
          len = 0;
 
242
          rc = write(filedes[1], &len, sizeof(int));
 
243
          rc = 1;
 
244
        }
 
245
      }
 
246
    } else if (!strcmp(ncOp, "ncDescribeInstances")) {
 
247
      char **instIds = va_arg(al, char **);
 
248
      int instIdsLen = va_arg(al, int);
 
249
      ncInstance ***ncOutInsts=va_arg(al, ncInstance ***);
 
250
      int *ncOutInstsLen= va_arg(al, int *);
 
251
 
 
252
      rc = ncDescribeInstancesStub(ncs, meta, instIds, instIdsLen, ncOutInsts, ncOutInstsLen);
 
253
      if (timeout && ncOutInsts && ncOutInstsLen) {
 
254
        if (!rc) {
 
255
          len = *ncOutInstsLen;
 
256
          rc = write(filedes[1], &len, sizeof(int));
 
257
          for (i=0; i<len; i++) {
 
258
            ncInstance *inst;
 
259
            inst = (*ncOutInsts)[i];
 
260
            rc = write(filedes[1], inst, sizeof(ncInstance));
 
261
          }
 
262
          rc = 0;
 
263
        } else {
 
264
          len = 0;
 
265
          rc = write(filedes[1], &len, sizeof(int));
 
266
          rc = 1;
 
267
        }      
 
268
      }
 
269
    } else if (!strcmp(ncOp, "ncDescribeResource")) {
 
270
      char *resourceType = va_arg(al, char *);
 
271
      ncResource **outRes=va_arg(al, ncResource **);
 
272
 
 
273
      rc = ncDescribeResourceStub(ncs, meta, resourceType, outRes);
 
274
      if (timeout && outRes) {
 
275
        if (!rc && *outRes) {
 
276
          len = sizeof(ncResource);
 
277
          rc = write(filedes[1], &len, sizeof(int));
 
278
          rc = write(filedes[1], *outRes, sizeof(ncResource));
 
279
          rc = 0;
 
280
        } else {
 
281
          len = 0;
 
282
          rc = write(filedes[1], &len, sizeof(int));
 
283
          rc = 1;
 
284
        }      
 
285
      }
 
286
    } else {
 
287
      logprintfl(EUCAWARN, "\tncClientCall(%s): ppid=%d operation '%s' not found\n", ncOp, getppid(), ncOp);
 
288
      rc = 1;
 
289
    }
 
290
    logprintfl(EUCADEBUG, "\tncClientCall(%s): ppid=%d done calling '%s' with exit code '%d'\n", ncOp, getppid(), ncOp, rc);
 
291
    if (rc) {
 
292
      ret = 1;
 
293
    } else {
 
294
      ret = 0;
 
295
    }
 
296
    close(filedes[1]);
 
297
    exit(ret);
 
298
  } else {
 
299
    // returns for each client call
 
300
    close(filedes[1]);
 
301
 
 
302
    if (!strcmp(ncOp, "ncGetConsoleOutput")) {
 
303
      char *instId = va_arg(al, char *);
 
304
      char **outConsoleOutput = va_arg(al, char **);
 
305
      if (outConsoleOutput) {
 
306
        *outConsoleOutput = NULL;
 
307
      }
 
308
      if (timeout && outConsoleOutput) {
 
309
        rbytes = timeread(filedes[0], &len, sizeof(int), timeout);
 
310
        if (rbytes <= 0) {
 
311
          kill(pid, SIGKILL);
 
312
          opFail=1;
 
313
        } else {
 
314
          *outConsoleOutput = malloc(sizeof(char) * len);
 
315
          if (!*outConsoleOutput) {
 
316
            logprintfl(EUCAFATAL, "ncClientCall(%s): out of memory!\n", ncOp);
 
317
            unlock_exit(1);
 
318
          }
 
319
          rbytes = timeread(filedes[0], *outConsoleOutput, len, timeout);
 
320
          if (rbytes <= 0) {
 
321
            kill(pid, SIGKILL);
 
322
            opFail=1;
 
323
          }
 
324
        }
 
325
      }
 
326
    } else if (!strcmp(ncOp, "ncTerminateInstance")) {
 
327
      char *instId = va_arg(al, char *);
 
328
      int *shutdownState = va_arg(al, int *);
 
329
      int *previousState = va_arg(al, int *);
 
330
      if (shutdownState && previousState) {
 
331
        *shutdownState = *previousState = 0;
 
332
      }
 
333
      if (timeout && shutdownState && previousState) {
 
334
        rbytes = timeread(filedes[0], &len, sizeof(int), timeout);
 
335
        if (rbytes <= 0) {
 
336
          kill(pid, SIGKILL);
 
337
          opFail=1;
 
338
        } else {
 
339
          rbytes = timeread(filedes[0], shutdownState, sizeof(int), timeout);
 
340
          if (rbytes <= 0) {
 
341
            kill(pid, SIGKILL);
 
342
            opFail=1;
 
343
          }
 
344
          rbytes = timeread(filedes[0], previousState, sizeof(int), timeout);
 
345
          if (rbytes <= 0) {
 
346
            kill(pid, SIGKILL);
 
347
            opFail=1;
 
348
          }
 
349
        }
 
350
      }
 
351
    } else if (!strcmp(ncOp, "ncStartNetwork")) {
 
352
      char **peers = va_arg(al, char **);
 
353
      int peersLen = va_arg(al, int);
 
354
      int port = va_arg(al, int);
 
355
      int vlan = va_arg(al, int);
 
356
      char **outStatus = va_arg(al, char **);
 
357
      if (outStatus) {
 
358
        *outStatus = NULL;
 
359
      }
 
360
      if (timeout && outStatus) {
 
361
        *outStatus = NULL;
 
362
        rbytes = timeread(filedes[0], &len, sizeof(int), timeout);
 
363
        if (rbytes <= 0) {
 
364
          kill(pid, SIGKILL);
 
365
          opFail=1;
 
366
        } else {
 
367
          *outStatus = malloc(sizeof(char) * len);
 
368
          if (!*outStatus) {
 
369
            logprintfl(EUCAFATAL, "ncClientCall(%s): out of memory!\n", ncOp);
 
370
            unlock_exit(1);
 
371
          }
 
372
          rbytes = timeread(filedes[0], *outStatus, len, timeout);
 
373
          if (rbytes <= 0) {
 
374
            kill(pid, SIGKILL);
 
375
            opFail=1;
 
376
          }
 
377
        }
 
378
      }
 
379
    } else if (!strcmp(ncOp, "ncRunInstance")) {
 
380
      char *instId = va_arg(al, char *);
 
381
      char *reservationId = va_arg(al, char *);
 
382
      virtualMachine *ncvm = va_arg(al, virtualMachine *);
 
383
      char *imageId = va_arg(al, char *);
 
384
      char *imageURL = va_arg(al, char *);
 
385
      char *kernelId = va_arg(al, char *);
 
386
      char *kernelURL = va_arg(al, char *);
 
387
      char *ramdiskId = va_arg(al, char *);
 
388
      char *ramdiskURL = va_arg(al, char *);
 
389
      char *keyName = va_arg(al, char *);
 
390
      netConfig *ncnet = va_arg(al, netConfig *);
 
391
      char *userData = va_arg(al, char *);
 
392
      char *launchIndex = va_arg(al, char *);
 
393
      char **netNames = va_arg(al, char **);
 
394
      int netNamesLen = va_arg(al, int);
 
395
      ncInstance **outInst = va_arg(al, ncInstance **);
 
396
      if (outInst) {
 
397
        *outInst = NULL;
 
398
      }
 
399
      if (timeout && outInst) {
 
400
        rbytes = timeread(filedes[0], &len, sizeof(int), timeout);
 
401
        if (rbytes <= 0) {
 
402
          kill(pid, SIGKILL);
 
403
          opFail=1;
 
404
        } else {
 
405
          *outInst = malloc(sizeof(ncInstance));
 
406
          if (!*outInst) {
 
407
            logprintfl(EUCAFATAL, "ncClientCall(%s): out of memory!\n", ncOp);
 
408
            unlock_exit(1);
 
409
          }
 
410
          rbytes = timeread(filedes[0], *outInst, sizeof(ncInstance), timeout);
 
411
          if (rbytes <= 0) {
 
412
            kill(pid, SIGKILL);
 
413
            opFail=1;
 
414
          }
 
415
        }
 
416
      }
 
417
    } else if (!strcmp(ncOp, "ncDescribeInstances")) {
 
418
      char **instIds = va_arg(al, char **);
 
419
      int instIdsLen = va_arg(al, int);
 
420
      ncInstance ***ncOutInsts=va_arg(al, ncInstance ***);
 
421
      int *ncOutInstsLen=va_arg(al, int *);
 
422
      if (ncOutInstsLen && ncOutInsts) {
 
423
        *ncOutInstsLen = 0;
 
424
        *ncOutInsts = NULL;
 
425
      }
 
426
      if (timeout && ncOutInsts && ncOutInstsLen) {
 
427
        rbytes = timeread(filedes[0], &len, sizeof(int), timeout);
 
428
        if (rbytes <= 0) {
 
429
          kill(pid, SIGKILL);
 
430
          opFail=1;
 
431
        } else {
 
432
          *ncOutInsts = malloc(sizeof(ncInstance *) * len);
 
433
          if (!*ncOutInsts) {
 
434
            logprintfl(EUCAFATAL, "ncClientCall(%s): out of memory!\n", ncOp);
 
435
            unlock_exit(1);
 
436
          }
 
437
          *ncOutInstsLen = len;
 
438
          for (i=0; i<len; i++) {
 
439
            ncInstance *inst;
 
440
            inst = malloc(sizeof(ncInstance));
 
441
            if (!inst) {
 
442
              logprintfl(EUCAFATAL, "ncClientCall(%s): out of memory!\n", ncOp);
 
443
              unlock_exit(1);
 
444
            }
 
445
            rbytes = timeread(filedes[0], inst, sizeof(ncInstance), timeout);
 
446
            (*ncOutInsts)[i] = inst;
 
447
          }
 
448
        }
 
449
      }
 
450
    } else if (!strcmp(ncOp, "ncDescribeResource")) {
 
451
      char *resourceType = va_arg(al, char *);
 
452
      ncResource **outRes=va_arg(al, ncResource **);
 
453
      if (outRes) {
 
454
        *outRes = NULL;
 
455
      }
 
456
      if (timeout && outRes) {
 
457
        rbytes = timeread(filedes[0], &len, sizeof(int), timeout);
 
458
        if (rbytes <= 0) {
 
459
          kill(pid, SIGKILL);
 
460
          opFail=1;
 
461
        } else {
 
462
          *outRes = malloc(sizeof(ncResource));
 
463
          if (!outRes) {
 
464
            logprintfl(EUCAFATAL, "ncClientCall(%s): out of memory!\n", ncOp);
 
465
            unlock_exit(1);
 
466
          }
 
467
          rbytes = timeread(filedes[0], *outRes, sizeof(ncResource), timeout);
 
468
          if (rbytes <= 0) {
 
469
            kill(pid, SIGKILL);
 
470
            opFail=1;
 
471
          }
 
472
        }
 
473
      }
 
474
    } else {
 
475
      // nothing to do in default case (succ/fail encoded in exit code)
 
476
    }
 
477
    
 
478
    close(filedes[0]);
 
479
    if (timeout) {
 
480
      rc = timewait(pid, &status, timeout);
 
481
      rc = WEXITSTATUS(status);
 
482
    } else {
 
483
      rc = 0;
 
484
    }
 
485
  }
 
486
 
 
487
  logprintfl(EUCADEBUG, "ncClientCall(%s): done clientrc=%d opFail=%d\n", ncOp, rc, opFail);
 
488
  if (rc || opFail) {
 
489
    ret = 1;
 
490
  } else {
 
491
    ret = 0;
 
492
  }
 
493
  
 
494
  // release the lock
 
495
  sem_mypost(ncLock);
 
496
  
 
497
  va_end(al);
 
498
  
 
499
  return(ret);
 
500
}
 
501
 
 
502
// calculate nc call timeout, based on when operation was started (op_start), the total number of calls to make (numCalls), and the current progress (idx)
 
503
int ncGetTimeout(time_t op_start, time_t op_max, int numCalls, int idx) {
 
504
  time_t op_timer, op_pernode;
 
505
  int numLeft;
 
506
 
 
507
  numLeft = numCalls - idx;
 
508
  if ( numLeft <= 0 ) {
 
509
    numLeft = 1;
 
510
  }
 
511
 
 
512
  op_timer = op_max - (time(NULL) - op_start);
 
513
  op_pernode = op_timer / numLeft;
 
514
 
 
515
  return(maxint(minint(op_pernode, OP_TIMEOUT_PERNODE), OP_TIMEOUT_MIN));
 
516
}
 
517
 
 
518
int doAttachVolume(ncMetadata *ccMeta, char *volumeId, char *instanceId, char *remoteDev, char *localDev) {
 
519
  int i, j, rc, start = 0, stop = 0, ret=0, done=0, timeout;
 
520
  ccInstance *myInstance;
 
521
  ncStub *ncs;
 
522
  time_t op_start;
 
523
  ccResourceCache resourceCacheLocal;
 
524
  
 
525
  i = j = 0;
 
526
  myInstance = NULL;
 
527
  op_start = time(NULL);
 
528
  
 
529
  rc = initialize();
 
530
  if (rc) {
 
531
    return(1);
 
532
  }
 
533
  
 
534
  logprintfl(EUCAINFO, "AttachVolume(): called\n");
 
535
  logprintfl(EUCADEBUG, "AttachVolume(): params: userId=%s, volumeId=%s, instanceId=%s, remoteDev=%s, localDev=%s\n", SP(ccMeta ? ccMeta->userId : "UNSET"), SP(volumeId), SP(instanceId), SP(remoteDev), SP(localDev));
 
536
  if (!volumeId || !instanceId || !remoteDev || !localDev) {
 
537
    logprintfl(EUCAERROR, "AttachVolume(): bad input params\n");
 
538
    return(1);
 
539
  }
 
540
  
 
541
  sem_mywait(RESCACHE);
 
542
  memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache));
 
543
  sem_mypost(RESCACHE);
 
544
  
 
545
  rc = find_instanceCacheId(instanceId, &myInstance);
 
546
  if (!rc) {
 
547
    // found the instance in the cache
 
548
    if (myInstance) {
 
549
      start = myInstance->ncHostIdx;
 
550
      stop = start+1;
 
551
      free(myInstance);
 
552
    }
 
553
  } else {
 
554
    start = 0;
 
555
    stop = resourceCacheLocal.numResources;
 
556
  }
 
557
  
 
558
  done=0;
 
559
  for (j=start; j<stop && !done; j++) {
 
560
    timeout = ncGetTimeout(op_start, OP_TIMEOUT, stop-start, j);
 
561
    rc = ncClientCall(ccMeta, timeout, NCCALL, resourceCacheLocal.resources[j].ncURL, "ncAttachVolume", instanceId, volumeId, remoteDev, localDev);
 
562
    if (rc) {
 
563
      ret = 1;
 
564
    } else {
 
565
      ret = 0;
 
566
      done++;
 
567
    }
 
568
  }
 
569
  
 
570
  logprintfl(EUCADEBUG,"AttachVolume(): done.\n");
 
571
  
 
572
  shawn();
 
573
 
 
574
  return(ret);
 
575
}
 
576
 
 
577
int doDetachVolume(ncMetadata *ccMeta, char *volumeId, char *instanceId, char *remoteDev, char *localDev, int force) {
 
578
  int i, j, rc, start = 0, stop = 0, ret=0, done=0, timeout;
 
579
  ccInstance *myInstance;
 
580
  ncStub *ncs;
 
581
  time_t op_start;
 
582
  ccResourceCache resourceCacheLocal;
 
583
  i = j = 0;
 
584
  myInstance = NULL;
 
585
  op_start = time(NULL);
 
586
  
 
587
  rc = initialize();
 
588
  if (rc) {
 
589
    return(1);
 
590
  }
 
591
  logprintfl(EUCAINFO, "DetachVolume(): called\n");
 
592
  logprintfl(EUCADEBUG, "DetachVolume(): params: userId=%s, volumeId=%s, instanceId=%s, remoteDev=%s, localDev=%s\n", SP(ccMeta ? ccMeta->userId : "UNSET"), SP(volumeId), SP(instanceId), SP(remoteDev), SP(localDev));
 
593
  if (!volumeId || !instanceId || !remoteDev || !localDev) {
 
594
    logprintfl(EUCAERROR, "DetachVolume(): bad input params\n");
 
595
    return(1);
 
596
  }
 
597
 
 
598
  sem_mywait(RESCACHE);
 
599
  memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache));
 
600
  sem_mypost(RESCACHE);
 
601
  
 
602
  rc = find_instanceCacheId(instanceId, &myInstance);
 
603
  if (!rc) {
 
604
    // found the instance in the cache
 
605
    if (myInstance) {
 
606
      start = myInstance->ncHostIdx;
 
607
      stop = start+1;
 
608
      free(myInstance);
 
609
    }
 
610
  } else {
 
611
    start = 0;
 
612
    stop = resourceCacheLocal.numResources;
 
613
  }
 
614
  
 
615
  for (j=start; j<stop; j++) {
 
616
    timeout = ncGetTimeout(op_start, OP_TIMEOUT, stop-start, j);
 
617
    rc = ncClientCall(ccMeta, timeout, NCCALL, resourceCacheLocal.resources[j].ncURL, "ncDetachVolume", instanceId, volumeId, remoteDev, localDev);
 
618
    if (rc) {
 
619
      ret = 1;
 
620
    } else {
 
621
      ret = 0;
 
622
      done++;
 
623
    }
 
624
  }
 
625
 
 
626
  logprintfl(EUCADEBUG,"DetachVolume(): done.\n");
 
627
  
 
628
  shawn();
 
629
  
 
630
  return(ret);
 
631
}
 
632
 
 
633
int doConfigureNetwork(ncMetadata *meta, char *type, int namedLen, char **sourceNames, char **userNames, int netLen, char **sourceNets, char *destName, char *destUserName, char *protocol, int minPort, int maxPort) {
 
634
  int rc, i, fail;
 
635
 
 
636
  rc = initialize();
 
637
  if (rc) {
 
638
    return(1);
 
639
  }
 
640
  
 
641
  logprintfl(EUCAINFO, "ConfigureNetwork(): called\n");
 
642
  logprintfl(EUCADEBUG, "ConfigureNetwork(): params: userId=%s, type=%s, namedLen=%d, netLen=%d, destName=%s, destUserName=%s, protocol=%s, minPort=%d, maxPort=%d\n", SP(meta->userId), SP(type), namedLen, netLen, SP(destName), SP(destUserName), SP(protocol), minPort, maxPort);
 
643
  
 
644
  if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) {
 
645
    fail = 0;
 
646
  } else {
 
647
    
 
648
    if (destUserName == NULL) {
 
649
      destUserName = meta->userId;
 
650
    }
 
651
    
 
652
    sem_mywait(VNET);
 
653
    
 
654
    fail=0;
 
655
    for (i=0; i<namedLen; i++) {
 
656
      if (sourceNames && userNames) {
 
657
        rc = vnetTableRule(vnetconfig, type, destUserName, destName, userNames[i], NULL, sourceNames[i], protocol, minPort, maxPort);
 
658
      }
 
659
      if (rc) {
 
660
        logprintfl(EUCAERROR,"ERROR: vnetTableRule() returned error\n");
 
661
        fail=1;
 
662
      }
 
663
    }
 
664
    for (i=0; i<netLen; i++) {
 
665
      if (sourceNets) {
 
666
        rc = vnetTableRule(vnetconfig, type, destUserName, destName, NULL, sourceNets[i], NULL, protocol, minPort, maxPort);
 
667
      }
 
668
      if (rc) {
 
669
        logprintfl(EUCAERROR,"ERROR: vnetTableRule() returned error\n");
 
670
        fail=1;
 
671
      }
 
672
    }
 
673
    sem_mypost(VNET);
 
674
  }
 
675
  
 
676
  logprintfl(EUCADEBUG,"ConfigureNetwork(): done\n");
 
677
  
 
678
  shawn();
 
679
  
 
680
  if (fail) {
 
681
    return(1);
 
682
  }
 
683
  return(0);
 
684
}
 
685
 
 
686
int doFlushNetwork(ncMetadata *ccMeta, char *destName) {
 
687
  int rc;
 
688
 
 
689
  if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) {
 
690
    return(0);
 
691
  }
 
692
 
 
693
  sem_mywait(VNET);
 
694
  rc = vnetFlushTable(vnetconfig, ccMeta->userId, destName);
 
695
  sem_mypost(VNET);
 
696
  return(rc);
 
697
}
 
698
 
 
699
int doAssignAddress(ncMetadata *ccMeta, char *src, char *dst) {
 
700
  int rc, allocated, addrdevno, ret;
 
701
  char cmd[MAX_PATH];
 
702
  ccInstance *myInstance=NULL;
 
703
 
 
704
  rc = initialize();
 
705
  if (rc) {
 
706
    return(1);
 
707
  }
 
708
  logprintfl(EUCAINFO,"AssignAddress(): called\n");
 
709
  logprintfl(EUCADEBUG,"AssignAddress(): params: src=%s, dst=%s\n", SP(src), SP(dst));
 
710
 
 
711
  if (!src || !dst || !strcmp(src, "0.0.0.0") || !strcmp(dst, "0.0.0.0")) {
 
712
    logprintfl(EUCADEBUG, "AssignAddress(): bad input params\n");
 
713
    return(1);
 
714
  }
 
715
  
 
716
  ret = 0;
 
717
  
 
718
  if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) {
 
719
    ret = 0;
 
720
  } else {
 
721
    
 
722
    sem_mywait(VNET);
 
723
    rc = vnetGetPublicIP(vnetconfig, src, NULL, &allocated, &addrdevno);
 
724
    if (rc) {
 
725
      logprintfl(EUCAERROR,"AssignAddress(): failed to retrieve publicip record %s\n", src);
 
726
      ret = 1;
 
727
    } else {
 
728
      if (!allocated) {
 
729
        snprintf(cmd, MAX_PATH, "%s/usr/lib/eucalyptus/euca_rootwrap ip addr add %s/32 dev %s", config->eucahome, src, vnetconfig->pubInterface);
 
730
        logprintfl(EUCADEBUG,"running cmd %s\n", cmd);
 
731
        rc = system(cmd);
 
732
        rc = rc>>8;
 
733
        if (rc && (rc != 2)) {
 
734
          logprintfl(EUCAERROR,"AssignAddress(): cmd '%s' failed\n", cmd);
 
735
          ret = 1;
 
736
        } else {
 
737
          rc = vnetAssignAddress(vnetconfig, src, dst);
 
738
          if (rc) {
 
739
            logprintfl(EUCAERROR,"AssignAddress(): vnetAssignAddress() failed\n");
 
740
            ret = 1;
 
741
          } else {
 
742
            rc = vnetAllocatePublicIP(vnetconfig, src, dst);
 
743
            if (rc) {
 
744
              logprintfl(EUCAERROR,"AssignAddress(): vnetAllocatePublicIP() failed\n");
 
745
              ret = 1;
 
746
            }
 
747
          }
 
748
        }
 
749
      } else {
 
750
        logprintfl(EUCAWARN,"AssignAddress(): ip %s is already assigned, ignoring\n", src);
 
751
        ret = 0;
 
752
      }
 
753
    }
 
754
    sem_mypost(VNET);
 
755
  }
 
756
  
 
757
  if (!ret) {
 
758
    // everything worked, update instance cache
 
759
 
 
760
    rc = map_instanceCache(privIpCmp, dst, pubIpSet, src);
 
761
    if (rc) {
 
762
      logprintfl(EUCAERROR, "AssignAddress(): map_instanceCache() failed to assign %s->%s\n", dst, src);
 
763
    }
 
764
  }
 
765
  
 
766
  logprintfl(EUCADEBUG,"AssignAddress(): done\n");  
 
767
  
 
768
  shawn();
 
769
 
 
770
  return(ret);
 
771
}
 
772
 
 
773
int doDescribePublicAddresses(ncMetadata *ccMeta, publicip **outAddresses, int *outAddressesLen) {
 
774
  int rc, ret;
 
775
  
 
776
  rc = initialize();
 
777
  if (rc) {
 
778
    return(1);
 
779
  }
 
780
  
 
781
  logprintfl(EUCAINFO, "DescribePublicAddresses(): called\n");
 
782
  logprintfl(EUCADEBUG, "DescribePublicAddresses(): params: userId=%s\n", SP(ccMeta ? ccMeta->userId : "UNSET"));
 
783
 
 
784
  ret=0;
 
785
  if (!strcmp(vnetconfig->mode, "MANAGED") || !strcmp(vnetconfig->mode, "MANAGED-NOVLAN")) {
 
786
    *outAddresses = vnetconfig->publicips;
 
787
    *outAddressesLen = NUMBER_OF_PUBLIC_IPS;
 
788
  } else {
 
789
    *outAddresses = NULL;
 
790
    *outAddressesLen = 0;
 
791
    ret=2;
 
792
  }
 
793
  
 
794
  logprintfl(EUCADEBUG, "DescribePublicAddresses(): done\n");
 
795
 
 
796
  shawn();
 
797
 
 
798
  return(ret);
 
799
}
 
800
 
 
801
int doUnassignAddress(ncMetadata *ccMeta, char *src, char *dst) {
 
802
  int rc, allocated, addrdevno, ret;
 
803
  char cmd[MAX_PATH];
 
804
  ccInstance *myInstance=NULL;
 
805
 
 
806
  rc = initialize();
 
807
  if (rc) {
 
808
    return(1);
 
809
  }
 
810
  logprintfl(EUCAINFO,"UnassignAddress(): called\n");
 
811
  logprintfl(EUCADEBUG,"UnassignAddress(): params: userId=%s, src=%s, dst=%s\n", SP(ccMeta ? ccMeta->userId : "UNSET"), SP(src), SP(dst));  
 
812
  
 
813
  if (!src || !dst || !strcmp(src, "0.0.0.0") || !strcmp(dst, "0.0.0.0")) {
 
814
    logprintfl(EUCADEBUG, "UnassignAddress(): bad input params\n");
 
815
    return(1);
 
816
  }
 
817
 
 
818
  if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) {
 
819
    ret = 0;
 
820
  } else {
 
821
    
 
822
    sem_mywait(VNET);
 
823
    ret=0;
 
824
    rc = vnetGetPublicIP(vnetconfig, src, NULL, &allocated, &addrdevno);
 
825
    if (rc) {
 
826
      logprintfl(EUCAERROR,"UnassignAddress(): failed to find publicip to unassign (%s)\n", src);
 
827
      ret=1;
 
828
    } else {
 
829
      if (allocated && dst) {
 
830
        rc = vnetUnassignAddress(vnetconfig, src, dst); 
 
831
        if (rc) {
 
832
          logprintfl(EUCAWARN,"vnetUnassignAddress() failed %d: %s/%s\n", rc, src, dst);
 
833
        }
 
834
        
 
835
        rc = vnetDeallocatePublicIP(vnetconfig, src, dst);
 
836
        if (rc) {
 
837
          logprintfl(EUCAWARN,"vnetDeallocatePublicIP() failed %d: %s\n", rc, src);
 
838
        }
 
839
      }
 
840
      
 
841
 
 
842
      snprintf(cmd, MAX_PATH, "%s/usr/lib/eucalyptus/euca_rootwrap ip addr del %s/32 dev %s", config->eucahome, src, vnetconfig->pubInterface);
 
843
      logprintfl(EUCADEBUG, "UnassignAddress(): running cmd '%s'\n", cmd);
 
844
      rc = system(cmd);
 
845
      if (rc) {
 
846
        logprintfl(EUCAWARN,"UnassignAddress(): cmd failed '%s'\n", cmd);
 
847
      }
 
848
    }
 
849
    sem_mypost(VNET);
 
850
  }
 
851
 
 
852
  if (!ret) {
 
853
    // refresh instance cache
 
854
    rc = map_instanceCache(pubIpCmp, src, pubIpSet, "0.0.0.0");
 
855
    if (rc) {
 
856
      logprintfl(EUCAERROR, "UnassignAddress(): map_instanceCache() failed to assign %s->%s\n", dst, src);
 
857
    }
 
858
  }
 
859
  
 
860
  logprintfl(EUCADEBUG,"UnassignAddress(): done\n");  
 
861
  
 
862
  shawn();
 
863
 
 
864
  return(ret);
 
865
}
 
866
 
 
867
int doStopNetwork(ncMetadata *ccMeta, char *netName, int vlan) {
 
868
  int rc, ret;
 
869
  
 
870
  rc = initialize();
 
871
  if (rc) {
 
872
    return(1);
 
873
  }
 
874
  
 
875
  logprintfl(EUCAINFO, "StopNetwork(): called\n");
 
876
  logprintfl(EUCADEBUG, "StopNetwork(): params: userId=%s, netName=%s, vlan=%d\n", SP(ccMeta ? ccMeta->userId : "UNSET"), SP(netName), vlan);
 
877
  if (!ccMeta || !netName || vlan < 0) {
 
878
    logprintfl(EUCAERROR, "StopNetwork(): bad input params\n");
 
879
  }
 
880
 
 
881
  if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) {
 
882
    ret = 0;
 
883
  } else {
 
884
    
 
885
    sem_mywait(VNET);
 
886
    if(ccMeta != NULL) {
 
887
      rc = vnetStopNetwork(vnetconfig, vlan, ccMeta->userId, netName);
 
888
    }
 
889
    ret = rc;
 
890
    sem_mypost(VNET);
 
891
  }
 
892
  
 
893
  logprintfl(EUCADEBUG,"StopNetwork(): done\n");
 
894
 
 
895
  shawn();
 
896
  
 
897
  return(ret);
 
898
}
 
899
 
 
900
int doDescribeNetworks(ncMetadata *ccMeta, char *nameserver, char **ccs, int ccsLen, vnetConfig *outvnetConfig) {
 
901
  int rc, i, j;
 
902
  
 
903
  rc = initialize();
 
904
  if (rc) {
 
905
    return(1);
 
906
  }
 
907
 
 
908
  logprintfl(EUCAINFO, "DescribeNetworks(): called\n");
 
909
  logprintfl(EUCADEBUG, "DescribeNetworks(): params: userId=%s, nameserver=%s, ccsLen=%d\n", SP(ccMeta ? ccMeta->userId : "UNSET"), SP(nameserver), ccsLen);
 
910
  
 
911
  sem_mywait(VNET);
 
912
  if (nameserver) {
 
913
    vnetconfig->euca_ns = dot2hex(nameserver);
 
914
  }
 
915
  if (!strcmp(vnetconfig->mode, "MANAGED") || !strcmp(vnetconfig->mode, "MANAGED-NOVLAN")) {
 
916
    rc = vnetSetCCS(vnetconfig, ccs, ccsLen);
 
917
    rc = vnetSetupTunnels(vnetconfig);
 
918
  }
 
919
  memcpy(outvnetConfig, vnetconfig, sizeof(vnetConfig));
 
920
 
 
921
  sem_mypost(VNET);
 
922
  logprintfl(EUCADEBUG, "DescribeNetworks(): done\n");
 
923
  
 
924
  shawn();
 
925
 
 
926
  return(0);
 
927
}
 
928
 
 
929
int doStartNetwork(ncMetadata *ccMeta, char *netName, int vlan, char *nameserver, char **ccs, int ccsLen) {
 
930
  int rc, ret;
 
931
  time_t op_start;
 
932
  char *brname;
 
933
  
 
934
  op_start = time(NULL);
 
935
 
 
936
  rc = initialize();
 
937
  if (rc) {
 
938
    return(1);
 
939
  }
 
940
  
 
941
  logprintfl(EUCAINFO, "StartNetwork(): called\n");
 
942
  logprintfl(EUCADEBUG, "StartNetwork(): params: userId=%s, netName=%s, vlan=%d, nameserver=%s, ccsLen=%d\n", SP(ccMeta ? ccMeta->userId : "UNSET"), SP(netName), vlan, SP(nameserver), ccsLen);
 
943
 
 
944
  if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) {
 
945
    ret = 0;
 
946
  } else {
 
947
    sem_mywait(VNET);
 
948
    if (nameserver) {
 
949
      vnetconfig->euca_ns = dot2hex(nameserver);
 
950
    }
 
951
    
 
952
    rc = vnetSetCCS(vnetconfig, ccs, ccsLen);
 
953
    rc = vnetSetupTunnels(vnetconfig);
 
954
 
 
955
    brname = NULL;
 
956
    rc = vnetStartNetwork(vnetconfig, vlan, ccMeta->userId, netName, &brname);
 
957
    if (brname) free(brname);
 
958
 
 
959
    sem_mypost(VNET);
 
960
    
 
961
    if (rc) {
 
962
      logprintfl(EUCAERROR,"StartNetwork(): vnetStartNetwork() failed (%d)\n", rc);
 
963
      ret = 1;
 
964
    } else {
 
965
      ret = 0;
 
966
    }
 
967
    
 
968
  }
 
969
  
 
970
  logprintfl(EUCADEBUG,"StartNetwork(): done\n");
 
971
  
 
972
  shawn();  
 
973
 
 
974
  return(ret);
 
975
}
 
976
 
 
977
int doDescribeResources(ncMetadata *ccMeta, virtualMachine **ccvms, int vmLen, int **outTypesMax, int **outTypesAvail, int *outTypesLen, char ***outServiceTags, int *outServiceTagsLen) {
 
978
  int i;
 
979
  int rc, diskpool, mempool, corepool;
 
980
  int j;
 
981
  ccResource *res;
 
982
  time_t op_start;
 
983
  ccResourceCache resourceCacheLocal;
 
984
  char strbuf[4096];
 
985
 
 
986
  logprintfl(EUCAINFO,"DescribeResources(): called\n");
 
987
  logprintfl(EUCADEBUG,"DescribeResources(): params: userId=%s, vmLen=%d\n", SP(ccMeta ? ccMeta->userId : "UNSET"), vmLen);
 
988
 
 
989
  op_start = time(NULL);
 
990
 
 
991
  rc = initialize();
 
992
  if (rc) {
 
993
    return(1);
 
994
  }
 
995
  
 
996
  if (outTypesMax == NULL || outTypesAvail == NULL || outTypesLen == NULL || outServiceTags == NULL || outServiceTagsLen == NULL) {
 
997
    // input error
 
998
    return(1);
 
999
  }
 
1000
  
 
1001
  *outTypesMax = NULL;
 
1002
  *outTypesAvail = NULL;
 
1003
  
 
1004
  *outTypesMax = malloc(sizeof(int) * vmLen);
 
1005
  *outTypesAvail = malloc(sizeof(int) * vmLen);
 
1006
  if (*outTypesMax == NULL || *outTypesAvail == NULL) {
 
1007
      logprintfl(EUCAERROR,"DescribeResources(): out of memory\n");
 
1008
      unlock_exit(1);
 
1009
  }
 
1010
  bzero(*outTypesMax, sizeof(int) * vmLen);
 
1011
  bzero(*outTypesAvail, sizeof(int) * vmLen);
 
1012
 
 
1013
  *outTypesLen = vmLen;
 
1014
 
 
1015
  for (i=0; i<vmLen; i++) {
 
1016
    if ((*ccvms)[i].mem <= 0 || (*ccvms)[i].cores <= 0 || (*ccvms)[i].disk <= 0) {
 
1017
      logprintfl(EUCAERROR,"DescribeResources(): input error\n");
 
1018
      if (*outTypesAvail) free(*outTypesAvail);
 
1019
      if (*outTypesMax) free(*outTypesMax);
 
1020
      *outTypesLen = 0;
 
1021
      *outServiceTags = NULL;
 
1022
      *outServiceTagsLen = 0;
 
1023
      return(1);
 
1024
    }
 
1025
  }
 
1026
 
 
1027
  sem_mywait(RESCACHE);
 
1028
  memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache));
 
1029
  sem_mypost(RESCACHE);
 
1030
  {
 
1031
    *outServiceTags = malloc(sizeof(char *) * resourceCacheLocal.numResources);
 
1032
    if (*outServiceTags == NULL) {
 
1033
      logprintfl(EUCAFATAL,"DescribeResources(): out of memory!\n");
 
1034
      unlock_exit(1);
 
1035
    } else {
 
1036
      *outServiceTagsLen = resourceCacheLocal.numResources;
 
1037
      for (i=0; i<resourceCacheLocal.numResources; i++) {
 
1038
        (*outServiceTags)[i] = strdup(resourceCacheLocal.resources[i].ncURL);
 
1039
        if ((*outServiceTags)[i] == NULL)  {
 
1040
          logprintfl(EUCAFATAL,"DescribeResources(): out of memory!\n");
 
1041
          unlock_exit(1);
 
1042
        }
 
1043
        
 
1044
      }
 
1045
    }
 
1046
 
 
1047
    for (i=0; i<resourceCacheLocal.numResources; i++) {
 
1048
      res = &(resourceCacheLocal.resources[i]);
 
1049
      
 
1050
      for (j=0; j<vmLen; j++) {
 
1051
        mempool = res->availMemory;
 
1052
        diskpool = res->availDisk;
 
1053
        corepool = res->availCores;
 
1054
        
 
1055
        mempool -= (*ccvms)[j].mem;
 
1056
        diskpool -= (*ccvms)[j].disk;
 
1057
        corepool -= (*ccvms)[j].cores;
 
1058
        while (mempool >= 0 && diskpool >= 0 && corepool >= 0) {
 
1059
          (*outTypesAvail)[j]++;
 
1060
          mempool -= (*ccvms)[j].mem;
 
1061
          diskpool -= (*ccvms)[j].disk;
 
1062
          corepool -= (*ccvms)[j].cores;
 
1063
        }
 
1064
        
 
1065
        mempool = res->maxMemory;
 
1066
        diskpool = res->maxDisk;
 
1067
        corepool = res->maxCores;
 
1068
        
 
1069
        mempool -= (*ccvms)[j].mem;
 
1070
        diskpool -= (*ccvms)[j].disk;
 
1071
        corepool -= (*ccvms)[j].cores;
 
1072
        while (mempool >= 0 && diskpool >= 0 && corepool >= 0) {
 
1073
          (*outTypesMax)[j]++;
 
1074
          mempool -= (*ccvms)[j].mem;
 
1075
          diskpool -= (*ccvms)[j].disk;
 
1076
          corepool -= (*ccvms)[j].cores;
 
1077
        }
 
1078
      }
 
1079
    }
 
1080
  }
 
1081
  
 
1082
  if (vmLen >= 5) {
 
1083
    logprintfl(EUCAINFO,"DescribeResources(): resource response summary (name{avail/max}): %s{%d/%d} %s{%d/%d} %s{%d/%d} %s{%d/%d} %s{%d/%d}\n", (*ccvms)[0].name, (*outTypesAvail)[0], (*outTypesMax)[0], (*ccvms)[1].name, (*outTypesAvail)[1], (*outTypesMax)[1], (*ccvms)[2].name, (*outTypesAvail)[2], (*outTypesMax)[2], (*ccvms)[3].name, (*outTypesAvail)[3], (*outTypesMax)[3], (*ccvms)[4].name, (*outTypesAvail)[4], (*outTypesMax)[4]);
 
1084
  }
 
1085
  logprintfl(EUCADEBUG,"DescribeResources(): done\n");
 
1086
  
 
1087
  shawn();
 
1088
 
 
1089
  return(0);
 
1090
}
 
1091
 
 
1092
int changeState(ccResource *in, int newstate) {
 
1093
  if (in == NULL) return(1);
 
1094
  if (in->state == newstate) return(0);
 
1095
  
 
1096
  in->lastState = in->state;
 
1097
  in->state = newstate;
 
1098
  in->stateChange = time(NULL);
 
1099
  in->idleStart = 0;
 
1100
  
 
1101
  return(0);
 
1102
}
 
1103
 
 
1104
int refresh_resources(ncMetadata *ccMeta, int timeout, int dolock) {
 
1105
  int i, rc, nctimeout;
 
1106
  int status, ret=0;
 
1107
  int filedes[2];  
 
1108
  time_t op_start;
 
1109
  ncStub *ncs;
 
1110
  ncResource *ncResDst=NULL;
 
1111
  ccResourceCache resourceCacheLocal;
 
1112
 
 
1113
  if (timeout <= 0) timeout = 1;
 
1114
  
 
1115
  op_start = time(NULL);
 
1116
  logprintfl(EUCAINFO,"refresh_resources(): called\n");
 
1117
 
 
1118
  rc = update_config();
 
1119
  if (rc) {
 
1120
    logprintfl(EUCAWARN, "refresh_resources(): bad return from update_config(), check your config file\n");
 
1121
  }
 
1122
  
 
1123
  // critical NC call section
 
1124
  sem_mywait(RESCACHE);
 
1125
  memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache));
 
1126
  sem_mypost(RESCACHE);
 
1127
  
 
1128
  for (i=0; i<resourceCacheLocal.numResources; i++) {
 
1129
    ncResDst=NULL;
 
1130
    if (resourceCacheLocal.resources[i].state != RESASLEEP && resourceCacheLocal.resources[i].running == 0) {
 
1131
      nctimeout = ncGetTimeout(op_start, timeout, resourceCacheLocal.numResources, i);
 
1132
      rc = ncClientCall(ccMeta, nctimeout, NCCALL, resourceCacheLocal.resources[i].ncURL, "ncDescribeResource", NULL, &ncResDst);
 
1133
      if (rc != 0) {
 
1134
        powerUp(&(resourceCacheLocal.resources[i]));
 
1135
        
 
1136
        if (resourceCacheLocal.resources[i].state == RESWAKING && ((time(NULL) - resourceCacheLocal.resources[i].stateChange) < config->wakeThresh)) {
 
1137
          logprintfl(EUCADEBUG, "refresh_resources(): resource still waking up (%d more seconds until marked as down)\n", config->wakeThresh - (time(NULL) - resourceCacheLocal.resources[i].stateChange));
 
1138
        } else{
 
1139
          logprintfl(EUCAERROR,"refresh_resources(): bad return from ncDescribeResource(%s) (%d)\n", resourceCacheLocal.resources[i].hostname, rc);
 
1140
          resourceCacheLocal.resources[i].maxMemory = 0;
 
1141
          resourceCacheLocal.resources[i].availMemory = 0;
 
1142
          resourceCacheLocal.resources[i].maxDisk = 0;
 
1143
          resourceCacheLocal.resources[i].availDisk = 0;
 
1144
          resourceCacheLocal.resources[i].maxCores = 0;
 
1145
          resourceCacheLocal.resources[i].availCores = 0;    
 
1146
          changeState(&(resourceCacheLocal.resources[i]), RESDOWN);
 
1147
        }
 
1148
      } else {
 
1149
        logprintfl(EUCADEBUG,"refresh_resources(): received data from node=%s mem=%d/%d disk=%d/%d cores=%d/%d\n", resourceCacheLocal.resources[i].hostname, ncResDst->memorySizeMax, ncResDst->memorySizeAvailable, ncResDst->diskSizeMax,  ncResDst->diskSizeAvailable, ncResDst->numberOfCoresMax, ncResDst->numberOfCoresAvailable);
 
1150
        resourceCacheLocal.resources[i].maxMemory = ncResDst->memorySizeMax;
 
1151
        resourceCacheLocal.resources[i].availMemory = ncResDst->memorySizeAvailable;
 
1152
        resourceCacheLocal.resources[i].maxDisk = ncResDst->diskSizeMax;
 
1153
        resourceCacheLocal.resources[i].availDisk = ncResDst->diskSizeAvailable;
 
1154
        resourceCacheLocal.resources[i].maxCores = ncResDst->numberOfCoresMax;
 
1155
        resourceCacheLocal.resources[i].availCores = ncResDst->numberOfCoresAvailable;    
 
1156
        changeState(&(resourceCacheLocal.resources[i]), RESUP);
 
1157
      }
 
1158
    } else {
 
1159
      logprintfl(EUCADEBUG, "refresh_resources(): resource asleep/running instances (%d), skipping resource update\n", resourceCacheLocal.resources[i].running);
 
1160
    }
 
1161
 
 
1162
    // try to discover the mac address of the resource
 
1163
    if (resourceCacheLocal.resources[i].mac[0] == '\0' && resourceCacheLocal.resources[i].ip[0] != '\0') {
 
1164
      char *mac;
 
1165
      rc = ip2mac(vnetconfig, resourceCacheLocal.resources[i].ip, &mac);
 
1166
      if (!rc) {
 
1167
        strncpy(resourceCacheLocal.resources[i].mac, mac, 24);
 
1168
        free(mac);
 
1169
        logprintfl(EUCADEBUG, "refresh_resources(): discovered MAC '%s' for host %s(%s)\n", resourceCacheLocal.resources[i].mac, resourceCacheLocal.resources[i].hostname, resourceCacheLocal.resources[i].ip);
 
1170
      }
 
1171
    }
 
1172
    if (ncResDst) free(ncResDst);
 
1173
  }
 
1174
 
 
1175
  sem_mywait(RESCACHE);
 
1176
  memcpy(resourceCache, &resourceCacheLocal, sizeof(ccResourceCache));
 
1177
  sem_mypost(RESCACHE);  
 
1178
 
 
1179
  logprintfl(EUCADEBUG,"refresh_resources(): done\n");
 
1180
  return(0);
 
1181
}
 
1182
 
 
1183
int refresh_instances(ncMetadata *ccMeta, int timeout, int dolock) {
 
1184
  ccInstance *myInstance=NULL;
 
1185
  int i, k, numInsts = 0, found, ncOutInstsLen, rc, pid, nctimeout;
 
1186
  time_t op_start;
 
1187
 
 
1188
  ncInstance **ncOutInsts=NULL;
 
1189
  ncStub *ncs;
 
1190
 
 
1191
  ccResourceCache resourceCacheLocal;
 
1192
 
 
1193
  op_start = time(NULL);
 
1194
 
 
1195
  logprintfl(EUCAINFO,"refresh_instances(): called\n");
 
1196
 
 
1197
  // critical NC call section
 
1198
  sem_mywait(RESCACHE);
 
1199
  memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache));
 
1200
  sem_mypost(RESCACHE);
 
1201
 
 
1202
  invalidate_instanceCache();
 
1203
 
 
1204
  for (i=0; i<resourceCacheLocal.numResources; i++) {
 
1205
    if (resourceCacheLocal.resources[i].state == RESUP) {
 
1206
      int j;
 
1207
      
 
1208
      nctimeout = ncGetTimeout(op_start, timeout, resourceCacheLocal.numResources, i);
 
1209
      rc = ncClientCall(ccMeta, nctimeout, NCCALL, resourceCacheLocal.resources[i].ncURL, "ncDescribeInstances", NULL, 0, &ncOutInsts, &ncOutInstsLen);
 
1210
      if (!rc) {
 
1211
 
 
1212
        // if idle, power down
 
1213
        if (ncOutInstsLen == 0) {
 
1214
          logprintfl(EUCADEBUG, "refresh_instances(): node %s idle since %d: (%d/%d) seconds\n", resourceCacheLocal.resources[i].hostname, resourceCacheLocal.resources[i].idleStart, time(NULL) - resourceCacheLocal.resources[i].idleStart, config->idleThresh); 
 
1215
          if (!resourceCacheLocal.resources[i].idleStart) {
 
1216
            resourceCacheLocal.resources[i].idleStart = time(NULL);
 
1217
          } else if ((time(NULL) - resourceCacheLocal.resources[i].idleStart) > config->idleThresh) {
 
1218
            // call powerdown
 
1219
            
 
1220
            if (powerDown(ccMeta, &(resourceCacheLocal.resources[i]))) {
 
1221
              logprintfl(EUCAWARN, "refresh_instances(): powerDown for %s failed\n", resourceCacheLocal.resources[i].hostname);
 
1222
            }
 
1223
          }
 
1224
        } else {
 
1225
          resourceCacheLocal.resources[i].idleStart = 0;
 
1226
        }
 
1227
        
 
1228
        // populate instanceCache
 
1229
        for (j=0; j<ncOutInstsLen; j++) {
 
1230
          found=1;
 
1231
          if (found) {
 
1232
            myInstance = NULL;
 
1233
            // add it
 
1234
            logprintfl(EUCADEBUG,"refresh_instances(): describing instance %s, %s, %d\n", ncOutInsts[j]->instanceId, ncOutInsts[j]->stateName, j);
 
1235
            numInsts++;
 
1236
            
 
1237
            // grab instance from cache, if available.  otherwise, start from scratch
 
1238
            rc = find_instanceCacheId(ncOutInsts[j]->instanceId, &myInstance);
 
1239
            if (rc || !myInstance) {
 
1240
              myInstance = malloc(sizeof(ccInstance));
 
1241
              if (!myInstance) {
 
1242
                logprintfl(EUCAFATAL, "refresh_instances(): out of memory!\n");
 
1243
                unlock_exit(1);
 
1244
              }
 
1245
              bzero(myInstance, sizeof(ccInstance));
 
1246
            }
 
1247
            
 
1248
            // update CC instance with instance state from NC 
 
1249
            rc = ccInstance_to_ncInstance(myInstance, ncOutInsts[j]);
 
1250
 
 
1251
            // instance info that the CC maintains
 
1252
            myInstance->ncHostIdx = i;
 
1253
            strncpy(myInstance->serviceTag, resourceCacheLocal.resources[i].ncURL, 64);
 
1254
            {
 
1255
              char *ip=NULL;
 
1256
              if (!strcmp(myInstance->ccnet.publicIp, "0.0.0.0")) {
 
1257
                if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) {
 
1258
                  rc = mac2ip(vnetconfig, myInstance->ccnet.privateMac, &ip);
 
1259
                  if (!rc) {
 
1260
                    strncpy(myInstance->ccnet.publicIp, ip, 24);
 
1261
                  }
 
1262
                }
 
1263
              }
 
1264
 
 
1265
              if (ip) free(ip);
 
1266
              ip=NULL;
 
1267
 
 
1268
              if (!strcmp(myInstance->ccnet.privateIp, "0.0.0.0")) {
 
1269
                rc = mac2ip(vnetconfig, myInstance->ccnet.privateMac, &ip);
 
1270
                if (!rc) {
 
1271
                  strncpy(myInstance->ccnet.privateIp, ip, 24);
 
1272
                }
 
1273
              }
 
1274
 
 
1275
              if (ip) free(ip);
 
1276
            }
 
1277
 
 
1278
            refresh_instanceCache(myInstance->instanceId, myInstance);
 
1279
            
 
1280
            logprintfl(EUCADEBUG, "refresh_instances(): storing instance state: %s/%s/%s/%s\n", myInstance->instanceId, myInstance->state, myInstance->ccnet.publicIp, myInstance->ccnet.privateIp);
 
1281
            print_ccInstance("refresh_instances(): ", myInstance);
 
1282
            
 
1283
            if (myInstance) free(myInstance);
 
1284
          }
 
1285
        }
 
1286
      }
 
1287
      if (ncOutInsts) {
 
1288
        for (j=0; j<ncOutInstsLen; j++) {
 
1289
          free_instance(&(ncOutInsts[j]));
 
1290
        }
 
1291
        free(ncOutInsts);
 
1292
        ncOutInsts = NULL;
 
1293
      }
 
1294
    }
 
1295
  }
 
1296
  
 
1297
  sem_mywait(RESCACHE);
 
1298
  memcpy(resourceCache, &resourceCacheLocal, sizeof(ccResourceCache));
 
1299
  sem_mypost(RESCACHE);
 
1300
  
 
1301
  logprintfl(EUCADEBUG,"refresh_instances(): done\n");  
 
1302
  return(0);
 
1303
}
 
1304
 
 
1305
int doDescribeInstances(ncMetadata *ccMeta, char **instIds, int instIdsLen, ccInstance **outInsts, int *outInstsLen) {
 
1306
  ccInstance *myInstance=NULL, *out=NULL, *cacheInstance=NULL;
 
1307
  int i, k, numInsts, found, ncOutInstsLen, rc, pid, count;
 
1308
  virtualMachine ccvm;
 
1309
  time_t op_start;
 
1310
 
 
1311
  ncInstance **ncOutInsts=NULL;
 
1312
  ncStub *ncs;
 
1313
 
 
1314
  logprintfl(EUCAINFO,"DescribeInstances(): called\n");
 
1315
  logprintfl(EUCADEBUG,"DescribeInstances(): params: userId=%s, instIdsLen=%d\n", SP(ccMeta ? ccMeta->userId : "UNSET"), instIdsLen);
 
1316
  
 
1317
  op_start = time(NULL);
 
1318
 
 
1319
  rc = initialize();
 
1320
  if (rc) {
 
1321
    return(1);
 
1322
  }
 
1323
 
 
1324
  *outInsts = NULL;
 
1325
  *outInstsLen = 0;
 
1326
 
 
1327
  sem_mywait(INSTCACHE);
 
1328
  count=0;
 
1329
  if (instanceCache->numInsts) {
 
1330
    *outInsts = malloc(sizeof(ccInstance) * instanceCache->numInsts);
 
1331
    if (!*outInsts) {
 
1332
      logprintfl(EUCAFATAL, "doDescribeInstances(): out of memory!\n");
 
1333
      unlock_exit(1);
 
1334
    }
 
1335
 
 
1336
    for (i=0; i<MAXINSTANCES; i++) {
 
1337
      if (instanceCache->cacheState[i] == INSTVALID) {
 
1338
        if (count >= instanceCache->numInsts) {
 
1339
          logprintfl(EUCAWARN, "doDescribeInstances(): found more instances than reported by numInsts, will only report a subset of instances\n");
 
1340
          count=0;
 
1341
        }
 
1342
        memcpy( &((*outInsts)[count]), &(instanceCache->instances[i]), sizeof(ccInstance));
 
1343
        count++;
 
1344
      }
 
1345
    }
 
1346
    
 
1347
    *outInstsLen = instanceCache->numInsts;
 
1348
  }
 
1349
  sem_mypost(INSTCACHE);
 
1350
 
 
1351
  for (i=0; i< (*outInstsLen) ; i++) {
 
1352
    logprintfl(EUCAINFO, "DescribeInstances(): instance response summary: instanceId=%s, state=%s, publicIp=%s, privateIp=%s\n", (*outInsts)[i].instanceId, (*outInsts)[i].state, (*outInsts)[i].ccnet.publicIp, (*outInsts)[i].ccnet.privateIp);
 
1353
  }
 
1354
 
 
1355
  logprintfl(EUCADEBUG,"DescribeInstances(): done\n");
 
1356
 
 
1357
  shawn();
 
1358
      
 
1359
  return(0);
 
1360
}
 
1361
 
 
1362
int powerUp(ccResource *res) {
 
1363
  int rc,ret,len, i;
 
1364
  char cmd[MAX_PATH], *bc=NULL;
 
1365
  uint32_t *ips=NULL, *nms=NULL;
 
1366
  
 
1367
  if (config->schedPolicy != SCHEDPOWERSAVE) {
 
1368
    return(0);
 
1369
  }
 
1370
 
 
1371
  rc = getdevinfo(vnetconfig->privInterface, &ips, &nms, &len);
 
1372
  if (rc) {
 
1373
 
 
1374
    ips = malloc(sizeof(uint32_t));
 
1375
    if (!ips) {
 
1376
      logprintfl(EUCAFATAL, "powerUp(): out of memory!\n");
 
1377
      unlock_exit(1);
 
1378
    }
 
1379
    
 
1380
    nms = malloc(sizeof(uint32_t));
 
1381
    if (!nms) {
 
1382
      logprintfl(EUCAFATAL, "powerUp(): out of memory!\n");
 
1383
      unlock_exit(1);
 
1384
    }
 
1385
 
 
1386
    ips[0] = 0xFFFFFFFF;
 
1387
    nms[0] = 0xFFFFFFFF;
 
1388
    len = 1;
 
1389
  }
 
1390
  
 
1391
  for (i=0; i<len; i++) {
 
1392
    logprintfl(EUCADEBUG, "powerUp(): attempting to wake up resource %s(%s/%s)\n", res->hostname, res->ip, res->mac);
 
1393
    // try to wake up res
 
1394
 
 
1395
    // broadcast
 
1396
    bc = hex2dot((0xFFFFFFFF - nms[i]) | (ips[i] & nms[i]));
 
1397
 
 
1398
    rc = 0;
 
1399
    ret = 0;
 
1400
    if (strcmp(res->mac, "00:00:00:00:00:00")) {
 
1401
      snprintf(cmd, MAX_PATH, "%s/usr/lib/eucalyptus/euca_rootwrap powerwake -b %s %s", vnetconfig->eucahome, bc, res->mac);
 
1402
    } else if (strcmp(res->ip, "0.0.0.0")) {
 
1403
      snprintf(cmd, MAX_PATH, "%s/usr/lib/eucalyptus/euca_rootwrap powerwake -b %s %s", vnetconfig->eucahome, bc, res->ip);
 
1404
    } else {
 
1405
      ret = rc = 1;
 
1406
    }
 
1407
    if (bc) free(bc);
 
1408
    if (!rc) {
 
1409
      logprintfl(EUCAINFO, "powerUp(): waking up powered off host %s(%s/%s): %s\n", res->hostname, res->ip, res->mac, cmd);
 
1410
      rc = system(cmd);
 
1411
      rc = rc>>8;
 
1412
      if (rc) {
 
1413
        logprintfl(EUCAERROR, "powerUp(): cmd failed: %d\n", rc);
 
1414
        ret = 1;
 
1415
      } else {
 
1416
        logprintfl(EUCAERROR, "powerUp(): cmd success: %d\n", rc);
 
1417
        changeState(res, RESWAKING);
 
1418
        ret = 0;
 
1419
      }
 
1420
    }
 
1421
  }
 
1422
  if (ips) free(ips);
 
1423
  if (nms) free(nms);
 
1424
  return(ret);
 
1425
}
 
1426
 
 
1427
int powerDown(ncMetadata *ccMeta, ccResource *node) {
 
1428
  int pid, rc, status, timeout;
 
1429
  ncStub *ncs=NULL;
 
1430
  time_t op_start;
 
1431
  
 
1432
  if (config->schedPolicy != SCHEDPOWERSAVE) {
 
1433
    node->idleStart = 0;
 
1434
    return(0);
 
1435
  }
 
1436
 
 
1437
  op_start = time(NULL);
 
1438
  
 
1439
  logprintfl(EUCAINFO, "powerDown(): sending powerdown to node: %s, %s\n", node->hostname, node->ncURL);
 
1440
  
 
1441
  timeout = ncGetTimeout(op_start, OP_TIMEOUT, 1, 1);
 
1442
  rc = ncClientCall(ccMeta, timeout, NCCALL, node->ncURL, "ncPowerDown");
 
1443
  
 
1444
  if (rc == 0) {
 
1445
    changeState(node, RESASLEEP);
 
1446
  }
 
1447
  return(rc);
 
1448
}
 
1449
 
 
1450
int ccInstance_to_ncInstance(ccInstance *dst, ncInstance *src) {
 
1451
  int i;
 
1452
  
 
1453
  strncpy(dst->instanceId, src->instanceId, 16);
 
1454
  strncpy(dst->reservationId, src->reservationId, 16);
 
1455
  strncpy(dst->ownerId, src->userId, 16);
 
1456
  strncpy(dst->amiId, src->imageId, 16);
 
1457
  strncpy(dst->kernelId, src->kernelId, 16);
 
1458
  strncpy(dst->ramdiskId, src->ramdiskId, 16);
 
1459
  strncpy(dst->keyName, src->keyName, 1024);
 
1460
  strncpy(dst->launchIndex, src->launchIndex, 64);
 
1461
  strncpy(dst->userData, src->userData, 4096);
 
1462
  strncpy(dst->state, src->stateName, 16);
 
1463
  dst->ts = src->launchTime;
 
1464
 
 
1465
  dst->ccnet.vlan = src->ncnet.vlan;
 
1466
  dst->ccnet.networkIndex = src->ncnet.networkIndex;
 
1467
  strncpy(dst->ccnet.privateMac, src->ncnet.privateMac, 24);
 
1468
  if (strcmp(src->ncnet.publicIp, "0.0.0.0") || dst->ccnet.publicIp[0] == '\0') strncpy(dst->ccnet.publicIp, src->ncnet.publicIp, 24);
 
1469
  if (strcmp(src->ncnet.privateIp, "0.0.0.0") || dst->ccnet.privateIp[0] == '\0') strncpy(dst->ccnet.privateIp, src->ncnet.privateIp, 24);
 
1470
 
 
1471
  for (i=0; i < src->groupNamesSize && i < 64; i++) {
 
1472
    snprintf(dst->groupNames[i], 32, "%s", src->groupNames[i]);
 
1473
  }
 
1474
 
 
1475
  memcpy(dst->volumes, src->volumes, sizeof(ncVolume) * EUCA_MAX_VOLUMES);
 
1476
  dst->volumesSize = src->volumesSize;
 
1477
 
 
1478
  memcpy(&(dst->ccvm), &(src->params), sizeof(virtualMachine));
 
1479
 
 
1480
  return(0);
 
1481
}
 
1482
 
 
1483
int schedule_instance(virtualMachine *vm, char *targetNode, int *outresid) {
 
1484
  int ret;
 
1485
  ncMetadata ccMeta;
 
1486
 
 
1487
  if (targetNode != NULL) {
 
1488
    ret = schedule_instance_explicit(vm, targetNode, outresid);
 
1489
  } else if (config->schedPolicy == SCHEDGREEDY) {
 
1490
    ret = schedule_instance_greedy(vm, outresid);
 
1491
  } else if (config->schedPolicy == SCHEDROUNDROBIN) {
 
1492
    ret = schedule_instance_roundrobin(vm, outresid);
 
1493
  } else if (config->schedPolicy == SCHEDPOWERSAVE) {
 
1494
    ret = schedule_instance_greedy(vm, outresid);
 
1495
  } else {
 
1496
    ret = schedule_instance_greedy(vm, outresid);
 
1497
  }
 
1498
 
 
1499
  return(ret);
 
1500
}
 
1501
 
 
1502
int schedule_instance_roundrobin(virtualMachine *vm, int *outresid) {
 
1503
  int i, done, start, found, resid=0;
 
1504
  ccResource *res;
 
1505
 
 
1506
  *outresid = 0;
 
1507
 
 
1508
  logprintfl(EUCADEBUG, "schedule(): scheduler using ROUNDROBIN policy to find next resource\n");
 
1509
  // find the best 'resource' on which to run the instance
 
1510
  done=found=0;
 
1511
  start = config->schedState;
 
1512
  i = start;
 
1513
  
 
1514
  logprintfl(EUCADEBUG, "schedule(): scheduler state starting at resource %d\n", config->schedState);
 
1515
  while(!done) {
 
1516
    int mem, disk, cores;
 
1517
    
 
1518
    res = &(resourceCache->resources[i]);
 
1519
    if (res->state != RESDOWN) {
 
1520
      mem = res->availMemory - vm->mem;
 
1521
      disk = res->availDisk - vm->disk;
 
1522
      cores = res->availCores - vm->cores;
 
1523
      
 
1524
      if (mem >= 0 && disk >= 0 && cores >= 0) {
 
1525
        resid = i;
 
1526
        found=1;
 
1527
        done++;
 
1528
      }
 
1529
    }
 
1530
    i++;
 
1531
    if (i >= resourceCache->numResources) {
 
1532
      i = 0;
 
1533
    }
 
1534
    if (i == start) {
 
1535
      done++;
 
1536
    }
 
1537
  }
 
1538
 
 
1539
  if (!found) {
 
1540
    // didn't find a resource
 
1541
    return(1);
 
1542
  }
 
1543
 
 
1544
  *outresid = resid;
 
1545
  config->schedState = i;
 
1546
 
 
1547
  logprintfl(EUCADEBUG, "schedule(): scheduler state finishing at resource %d\n", config->schedState);
 
1548
 
 
1549
  return(0);
 
1550
}
 
1551
 
 
1552
int schedule_instance_explicit(virtualMachine *vm, char *targetNode, int *outresid) {
 
1553
  int i, rc, done, resid, sleepresid;
 
1554
  ccResource *res;
 
1555
  
 
1556
  *outresid = 0;
 
1557
 
 
1558
  logprintfl(EUCADEBUG, "schedule(): scheduler using EXPLICIT policy to run VM on target node '%s'\n", targetNode);
 
1559
 
 
1560
  // find the best 'resource' on which to run the instance
 
1561
  resid = sleepresid = -1;
 
1562
  done=0;
 
1563
  for (i=0; i<resourceCache->numResources && !done; i++) {
 
1564
    int mem, disk, cores;
 
1565
    
 
1566
    res = &(resourceCache->resources[i]);
 
1567
    if (!strcmp(res->hostname, targetNode)) {
 
1568
      done++;
 
1569
      if (res->state == RESUP) {
 
1570
        mem = res->availMemory - vm->mem;
 
1571
        disk = res->availDisk - vm->disk;
 
1572
        cores = res->availCores - vm->cores;
 
1573
        
 
1574
        if (mem >= 0 && disk >= 0 && cores >= 0) {
 
1575
          resid = i;
 
1576
        }
 
1577
      } else if (res->state == RESASLEEP) {
 
1578
        mem = res->availMemory - vm->mem;
 
1579
        disk = res->availDisk - vm->disk;
 
1580
        cores = res->availCores - vm->cores;
 
1581
        
 
1582
        if (mem >= 0 && disk >= 0 && cores >= 0) {
 
1583
          sleepresid = i;
 
1584
        }
 
1585
      }
 
1586
    }
 
1587
  }
 
1588
  
 
1589
  if (resid == -1 && sleepresid == -1) {
 
1590
    // target resource is unavailable
 
1591
    return(1);
 
1592
  }
 
1593
  
 
1594
  if (resid != -1) {
 
1595
    res = &(resourceCache->resources[resid]);
 
1596
    *outresid = resid;
 
1597
  } else if (sleepresid != -1) {
 
1598
    res = &(resourceCache->resources[sleepresid]);
 
1599
    *outresid = sleepresid;
 
1600
  }
 
1601
  if (res->state == RESASLEEP) {
 
1602
    rc = powerUp(res);
 
1603
  }
 
1604
 
 
1605
  return(0);
 
1606
}
 
1607
 
 
1608
int schedule_instance_greedy(virtualMachine *vm, int *outresid) {
 
1609
  int i, rc, done, resid, sleepresid;
 
1610
  ccResource *res;
 
1611
  
 
1612
  *outresid = 0;
 
1613
 
 
1614
  if (config->schedPolicy == SCHEDGREEDY) {
 
1615
    logprintfl(EUCADEBUG, "schedule(): scheduler using GREEDY policy to find next resource\n");
 
1616
  } else if (config->schedPolicy == SCHEDPOWERSAVE) {
 
1617
    logprintfl(EUCADEBUG, "schedule(): scheduler using POWERSAVE policy to find next resource\n");
 
1618
  }
 
1619
 
 
1620
  // find the best 'resource' on which to run the instance
 
1621
  resid = sleepresid = -1;
 
1622
  done=0;
 
1623
  for (i=0; i<resourceCache->numResources && !done; i++) {
 
1624
    int mem, disk, cores;
 
1625
    
 
1626
    res = &(resourceCache->resources[i]);
 
1627
    if ((res->state == RESUP || res->state == RESWAKING) && resid == -1) {
 
1628
      mem = res->availMemory - vm->mem;
 
1629
      disk = res->availDisk - vm->disk;
 
1630
      cores = res->availCores - vm->cores;
 
1631
      
 
1632
      if (mem >= 0 && disk >= 0 && cores >= 0) {
 
1633
        resid = i;
 
1634
        done++;
 
1635
      }
 
1636
    } else if (res->state == RESASLEEP && sleepresid == -1) {
 
1637
      mem = res->availMemory - vm->mem;
 
1638
      disk = res->availDisk - vm->disk;
 
1639
      cores = res->availCores - vm->cores;
 
1640
      
 
1641
      if (mem >= 0 && disk >= 0 && cores >= 0) {
 
1642
        sleepresid = i;
 
1643
      }
 
1644
    }
 
1645
  }
 
1646
  
 
1647
  if (resid == -1 && sleepresid == -1) {
 
1648
    // didn't find a resource
 
1649
    return(1);
 
1650
  }
 
1651
  
 
1652
  if (resid != -1) {
 
1653
    res = &(resourceCache->resources[resid]);
 
1654
    *outresid = resid;
 
1655
  } else if (sleepresid != -1) {
 
1656
    res = &(resourceCache->resources[sleepresid]);
 
1657
    *outresid = sleepresid;
 
1658
  }
 
1659
  if (res->state == RESASLEEP) {
 
1660
    rc = powerUp(res);
 
1661
  }
 
1662
 
 
1663
  return(0);
 
1664
}
 
1665
 
 
1666
int doRunInstances(ncMetadata *ccMeta, char *amiId, char *kernelId, char *ramdiskId, char *amiURL, char *kernelURL, char *ramdiskURL, char **instIds, int instIdsLen, char **netNames, int netNamesLen, char **macAddrs, int macAddrsLen, int *networkIndexList, int networkIndexListLen, int minCount, int maxCount, char *ownerId, char *reservationId, virtualMachine *ccvm, char *keyName, int vlan, char *userData, char *launchIndex, char *targetNode, ccInstance **outInsts, int *outInstsLen) {
 
1667
  int rc=0, i=0, done=0, runCount=0, resid=0, foundnet=0, error=0, networkIdx=0, nidx=0, thenidx=0;
 
1668
  ccInstance *myInstance=NULL, 
 
1669
    *retInsts=NULL;
 
1670
  char instId[16];
 
1671
  time_t op_start=0;
 
1672
  ccResource *res=NULL;
 
1673
  char mac[32], privip[32], pubip[32];
 
1674
  
 
1675
  ncInstance *outInst=NULL;
 
1676
  virtualMachine ncvm;
 
1677
  netConfig ncnet;
 
1678
  ncStub *ncs=NULL;
 
1679
  
 
1680
  op_start = time(NULL);
 
1681
  
 
1682
  rc = initialize();
 
1683
  if (rc) {
 
1684
    return(1);
 
1685
  }
 
1686
  logprintfl(EUCAINFO,"RunInstances(): called\n");
 
1687
  logprintfl(EUCADEBUG,"RunInstances(): params: userId=%s, emiId=%s, kernelId=%s, ramdiskId=%s, emiURL=%s, kernelURL=%s, ramdiskURL=%s, instIdsLen=%d, netNamesLen=%d, macAddrsLen=%d, networkIndexListLen=%d, minCount=%d, maxCount=%d, ownerId=%s, reservationId=%s, keyName=%s, vlan=%d, userData=%s, launchIndex=%s, targetNode=%s\n", SP(ccMeta ? ccMeta->userId : "UNSET"), SP(amiId), SP(kernelId), SP(ramdiskId), SP(amiURL), SP(kernelURL), SP(ramdiskURL), instIdsLen, netNamesLen, macAddrsLen, networkIndexListLen, minCount, maxCount, SP(ownerId), SP(reservationId), SP(keyName), vlan, SP(userData), SP(launchIndex), SP(targetNode));
 
1688
  
 
1689
  *outInstsLen = 0;
 
1690
  
 
1691
  if (!ccvm) {
 
1692
    logprintfl(EUCAERROR,"RunInstances(): invalid ccvm\n");
 
1693
    return(-1);
 
1694
  }
 
1695
  if (minCount <= 0 || maxCount <= 0 || instIdsLen < maxCount) {
 
1696
    logprintfl(EUCAERROR,"RunInstances(): bad min or max count, or not enough instIds (%d, %d, %d)\n", minCount, maxCount, instIdsLen);
 
1697
    return(-1);
 
1698
  }
 
1699
 
 
1700
  // check health of the networkIndexList
 
1701
  if ( (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) || networkIndexList == NULL) {
 
1702
    // disabled
 
1703
    nidx=-1;
 
1704
  } else {
 
1705
    if ( (networkIndexListLen < minCount) || (networkIndexListLen > maxCount) ) {
 
1706
      logprintfl(EUCAERROR, "RunInstances(): network index length (%d) is out of bounds for min/max instances (%d-%d)\n", networkIndexListLen, minCount, maxCount);
 
1707
      return(1);
 
1708
    }
 
1709
    for (i=0; i<networkIndexListLen; i++) {
 
1710
      if ( (networkIndexList[i] < 0) || (networkIndexList[i] > (vnetconfig->numaddrs-1)) ) {
 
1711
        logprintfl(EUCAERROR, "RunInstances(): network index (%d) out of bounds (0-%d)\n", networkIndexList[i], vnetconfig->numaddrs-1);
 
1712
        return(1);
 
1713
      }
 
1714
    }
 
1715
 
 
1716
    // all checked out
 
1717
    nidx=0;
 
1718
  }
 
1719
  
 
1720
  retInsts = malloc(sizeof(ccInstance) * maxCount);  
 
1721
  if (!retInsts) {
 
1722
    logprintfl(EUCAFATAL, "RunInstances(): out of memory!\n");
 
1723
    unlock_exit(1);
 
1724
  }
 
1725
 
 
1726
  runCount=0;
 
1727
  
 
1728
  // get updated resource information
 
1729
 
 
1730
  done=0;
 
1731
  for (i=0; i<maxCount && !done; i++) {
 
1732
    snprintf(instId, 16, "%s", instIds[i]);
 
1733
 
 
1734
    logprintfl(EUCADEBUG,"RunInstances(): running instance %s with emiId %s...\n", instId, amiId);
 
1735
    
 
1736
    // generate new mac
 
1737
    bzero(mac, 32);
 
1738
    bzero(pubip, 32);
 
1739
    bzero(privip, 32);
 
1740
    
 
1741
    strncpy(pubip, "0.0.0.0", 32);
 
1742
    strncpy(privip, "0.0.0.0", 32);
 
1743
    if (macAddrsLen >= maxCount) {
 
1744
      strncpy(mac, macAddrs[i], 32);
 
1745
    }      
 
1746
 
 
1747
    sem_mywait(VNET);
 
1748
    if (nidx == -1) {
 
1749
      rc = vnetGenerateNetworkParams(vnetconfig, instId, vlan, -1, mac, pubip, privip);
 
1750
      thenidx = -1;
 
1751
    } else {
 
1752
      rc = vnetGenerateNetworkParams(vnetconfig, instId, vlan, networkIndexList[nidx], mac, pubip, privip);
 
1753
      thenidx=nidx;
 
1754
      nidx++;
 
1755
    }
 
1756
    if (rc) {
 
1757
      foundnet = 0;
 
1758
    } else {
 
1759
      foundnet = 1;
 
1760
    }
 
1761
    sem_mypost(VNET);
 
1762
    
 
1763
    if (thenidx != -1) {
 
1764
      logprintfl(EUCADEBUG,"RunInstances(): assigning MAC/IP: %s/%s/%s/%d\n", mac, pubip, privip, networkIndexList[thenidx]);
 
1765
    } else {
 
1766
      logprintfl(EUCADEBUG,"RunInstances(): assigning MAC/IP: %s/%s/%s/%d\n", mac, pubip, privip, thenidx);
 
1767
    }
 
1768
    
 
1769
    if (mac[0] == '\0' || !foundnet) {
 
1770
      logprintfl(EUCAERROR,"RunInstances(): could not find/initialize any free network address, failing doRunInstances()\n");
 
1771
    } else {
 
1772
      // "run" the instance
 
1773
      memcpy (&ncvm, ccvm, sizeof(virtualMachine));
 
1774
      
 
1775
      ncnet.vlan = vlan;
 
1776
      if (thenidx >= 0) {
 
1777
        ncnet.networkIndex = networkIndexList[thenidx];
 
1778
      } else {
 
1779
        ncnet.networkIndex = -1;
 
1780
      }
 
1781
      snprintf(ncnet.privateMac, 24, "%s", mac);
 
1782
      snprintf(ncnet.privateIp, 24, "%s", privip);
 
1783
      snprintf(ncnet.publicIp, 24, "%s", pubip);
 
1784
      
 
1785
      sem_mywait(RESCACHE);
 
1786
 
 
1787
      resid = 0;
 
1788
      
 
1789
      sem_mywait(CONFIG);
 
1790
      rc = schedule_instance(ccvm, targetNode, &resid);
 
1791
      sem_mypost(CONFIG);
 
1792
 
 
1793
      res = &(resourceCache->resources[resid]);
 
1794
      if (rc) {
 
1795
        // could not find resource
 
1796
        logprintfl(EUCAERROR, "RunInstances(): scheduler could not find resource to run the instance on\n");
 
1797
        // couldn't run this VM, remove networking information from system
 
1798
        free_instanceNetwork(mac, vlan, 1, 1);
 
1799
      } else {
 
1800
        int pid, status, ret, rbytes;
 
1801
        
 
1802
        // try to run the instance on the chosen resource
 
1803
        logprintfl(EUCADEBUG, "RunInstances(): scheduler decided to run instance '%s' on resource '%s', running count '%d'\n", instId, res->ncURL, res->running);
 
1804
        
 
1805
        outInst=NULL;
 
1806
        
 
1807
        pid = fork();
 
1808
        if (pid == 0) {
 
1809
          time_t startRun;
 
1810
 
 
1811
          sem_mywait(RESCACHE);
 
1812
          if (res->running > 0) {
 
1813
            res->running++;
 
1814
          }
 
1815
          sem_mypost(RESCACHE);
 
1816
 
 
1817
          ret=0;
 
1818
          logprintfl(EUCAINFO,"RunInstances(): sending run instance: node=%s instanceId=%s emiId=%s mac=%s privIp=%s pubIp=%s vlan=%d networkIdx=%d key=%.32s... mem=%d disk=%d cores=%d\n", res->ncURL, instId, SP(amiId), ncnet.privateMac, ncnet.privateIp, ncnet.publicIp, ncnet.vlan, ncnet.networkIndex, SP(keyName), ncvm.mem, ncvm.disk, ncvm.cores);
 
1819
          rc = 1;
 
1820
          startRun = time(NULL);
 
1821
          while(rc && ((time(NULL) - startRun) < config->wakeThresh)){
 
1822
            int clientpid;
 
1823
 
 
1824
            // call StartNetwork client
 
1825
            rc = ncClientCall(ccMeta, OP_TIMEOUT_PERNODE, NCCALL, res->ncURL, "ncStartNetwork", NULL, 0, 0, vlan, NULL);
 
1826
 
 
1827
            rc = ncClientCall(ccMeta, OP_TIMEOUT_PERNODE, NCCALL, res->ncURL, "ncRunInstance", instId, reservationId, &ncvm, amiId, amiURL, kernelId, kernelURL, ramdiskId, ramdiskURL, keyName, &ncnet, userData, launchIndex, netNames, netNamesLen, &outInst);
 
1828
 
 
1829
            if (rc) {
 
1830
              sleep(1);
 
1831
            }
 
1832
          }
 
1833
          if (!rc) {
 
1834
            ret = 0;
 
1835
          } else {
 
1836
            ret = 1;
 
1837
          }
 
1838
          
 
1839
          sem_mywait(RESCACHE);
 
1840
          if (res->running > 0) {
 
1841
            res->running--;
 
1842
          }
 
1843
          sem_mypost(RESCACHE);
 
1844
 
 
1845
          exit(ret);
 
1846
        } else {
 
1847
          rc = 0;
 
1848
          logprintfl(EUCADEBUG,"RunInstances(): call complete (pid/rc): %d/%d\n", pid, rc);
 
1849
        }
 
1850
        if (rc != 0) {
 
1851
          // problem
 
1852
          logprintfl(EUCAERROR, "RunInstances(): tried to run the VM, but runInstance() failed; marking resource '%s' as down\n", res->ncURL);
 
1853
          res->state = RESDOWN;
 
1854
          i--;
 
1855
          // couldn't run this VM, remove networking information from system
 
1856
          free_instanceNetwork(mac, vlan, 1, 1);
 
1857
        } else {
 
1858
          res->availMemory -= ccvm->mem;
 
1859
          res->availDisk -= ccvm->disk;
 
1860
          res->availCores -= ccvm->cores;
 
1861
 
 
1862
          logprintfl(EUCADEBUG, "RunInstances(): resource information after schedule/run: %d/%d, %d/%d, %d/%d\n", res->availMemory, res->maxMemory, res->availCores, res->maxCores, res->availDisk, res->maxDisk);
 
1863
 
 
1864
          myInstance = &(retInsts[runCount]);
 
1865
          bzero(myInstance, sizeof(ccInstance));
 
1866
          
 
1867
          allocate_ccInstance(myInstance, instId, amiId, kernelId, ramdiskId, amiURL, kernelURL, ramdiskURL, ownerId, "Pending", time(NULL), reservationId, &ncnet, ccvm, resid, keyName, resourceCache->resources[resid].ncURL, userData, launchIndex, myInstance->groupNames, myInstance->volumes, myInstance->volumesSize);
 
1868
 
 
1869
          // start up DHCP
 
1870
          sem_mywait(CONFIG);
 
1871
          config->kick_dhcp = 1;
 
1872
          sem_mypost(CONFIG);
 
1873
 
 
1874
          // add the instance to the cache, and continue on
 
1875
          add_instanceCache(myInstance->instanceId, myInstance);
 
1876
          print_ccInstance("RunInstances(): ", myInstance);
 
1877
          
 
1878
          runCount++;
 
1879
        }
 
1880
      }
 
1881
 
 
1882
      sem_mypost(RESCACHE);
 
1883
 
 
1884
    }
 
1885
    
 
1886
  }
 
1887
  *outInstsLen = runCount;
 
1888
  *outInsts = retInsts;
 
1889
  
 
1890
  logprintfl(EUCADEBUG,"RunInstances(): done\n");
 
1891
  
 
1892
  shawn();
 
1893
 
 
1894
  if (error) {
 
1895
    return(1);
 
1896
  }
 
1897
  return(0);
 
1898
}
 
1899
 
 
1900
int doGetConsoleOutput(ncMetadata *meta, char *instId, char **outConsoleOutput) {
 
1901
  int i, j, rc, numInsts, start, stop, done, ret, rbytes, timeout=0;
 
1902
  ccInstance *myInstance;
 
1903
  ncStub *ncs;
 
1904
  char *consoleOutput;
 
1905
  time_t op_start;
 
1906
  ccResourceCache resourceCacheLocal;
 
1907
 
 
1908
  i = j = numInsts = 0;
 
1909
  op_start = time(NULL);
 
1910
 
 
1911
  consoleOutput = NULL;
 
1912
  myInstance = NULL;
 
1913
  
 
1914
  *outConsoleOutput = NULL;
 
1915
 
 
1916
  rc = initialize();
 
1917
  if (rc) {
 
1918
    return(1);
 
1919
  }
 
1920
 
 
1921
  logprintfl(EUCAINFO,"GetConsoleOutput(): called\n");
 
1922
  logprintfl(EUCADEBUG,"GetConsoleOutput(): params: userId=%s, instId=%s\n", SP(meta->userId), SP(instId));
 
1923
 
 
1924
  sem_mywait(RESCACHE);
 
1925
  memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache));
 
1926
  sem_mypost(RESCACHE);
 
1927
 
 
1928
  rc = find_instanceCacheId(instId, &myInstance);
 
1929
  if (!rc) {
 
1930
    // found the instance in the cache
 
1931
    start = myInstance->ncHostIdx;
 
1932
    stop = start+1;      
 
1933
    free(myInstance);
 
1934
  } else {
 
1935
    start = 0;
 
1936
    stop = resourceCacheLocal.numResources;
 
1937
  }
 
1938
 
 
1939
  done=0;
 
1940
  for (j=start; j<stop && !done; j++) {
 
1941
    if (*outConsoleOutput) free(*outConsoleOutput);
 
1942
    timeout = ncGetTimeout(op_start, timeout, (stop - start), j);
 
1943
    rc = ncClientCall(meta, timeout, NCCALL, resourceCacheLocal.resources[j].ncURL, "ncGetConsoleOutput", instId, outConsoleOutput);
 
1944
  
 
1945
    if (rc) {
 
1946
      ret = 1;
 
1947
    } else {
 
1948
      ret = 0;
 
1949
      done++;
 
1950
    }
 
1951
  }
 
1952
  
 
1953
  logprintfl(EUCADEBUG,"GetConsoleOutput(): done.\n");
 
1954
  
 
1955
  shawn();
 
1956
 
 
1957
  return(ret);
 
1958
}
 
1959
 
 
1960
int doRebootInstances(ncMetadata *meta, char **instIds, int instIdsLen) {
 
1961
  int i, j, rc, numInsts, start, stop, done, timeout=0, ret=0;
 
1962
  char *instId;
 
1963
  ccInstance *myInstance;
 
1964
  ncStub *ncs;
 
1965
  time_t op_start;
 
1966
  ccResourceCache resourceCacheLocal;
 
1967
 
 
1968
  i = j = numInsts = 0;
 
1969
  instId = NULL;
 
1970
  myInstance = NULL;
 
1971
  op_start = time(NULL);
 
1972
 
 
1973
  rc = initialize();
 
1974
  if (rc) {
 
1975
    return(1);
 
1976
  }
 
1977
  logprintfl(EUCAINFO,"RebootInstances(): called\n");
 
1978
  logprintfl(EUCADEBUG,"RebootInstances(): params: userId=%s, instIdsLen=%d\n", SP(meta->userId), instIdsLen);
 
1979
  
 
1980
  sem_mywait(RESCACHE);
 
1981
  memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache));
 
1982
  sem_mypost(RESCACHE);
 
1983
 
 
1984
  for (i=0; i<instIdsLen; i++) {
 
1985
    instId = instIds[i];
 
1986
    rc = find_instanceCacheId(instId, &myInstance);
 
1987
    if (!rc) {
 
1988
      // found the instance in the cache
 
1989
      start = myInstance->ncHostIdx;
 
1990
      stop = start+1;      
 
1991
      free(myInstance);
 
1992
    } else {
 
1993
      start = 0;
 
1994
      stop = resourceCacheLocal.numResources;
 
1995
    }
 
1996
    
 
1997
    done=0;
 
1998
    for (j=start; j<stop && !done; j++) {
 
1999
      timeout = ncGetTimeout(op_start, OP_TIMEOUT, (stop - start), j);
 
2000
      rc = ncClientCall(meta, timeout, NCCALL, resourceCacheLocal.resources[j].ncURL, "ncRebootInstance", instId);
 
2001
      if (rc) {
 
2002
        ret = 1;
 
2003
      } else {
 
2004
        ret = 0;
 
2005
        done++;
 
2006
      }      
 
2007
    }
 
2008
  }
 
2009
  
 
2010
  logprintfl(EUCADEBUG,"RebootInstances(): done.\n");
 
2011
 
 
2012
  shawn();
 
2013
 
 
2014
  return(0);
 
2015
}
 
2016
 
 
2017
int doTerminateInstances(ncMetadata *ccMeta, char **instIds, int instIdsLen, int **outStatus) {
 
2018
  int i, j, shutdownState, previousState, rc, start, stop, done=0, timeout, ret=0;
 
2019
  char *instId;
 
2020
  ccInstance *myInstance=NULL;
 
2021
  ncStub *ncs;
 
2022
  time_t op_start;
 
2023
  ccResourceCache resourceCacheLocal;
 
2024
 
 
2025
  i = j = 0;
 
2026
  instId = NULL;
 
2027
  myInstance = NULL;
 
2028
  op_start = time(NULL);
 
2029
  
 
2030
  rc = initialize();
 
2031
  if (rc) {
 
2032
    return(1);
 
2033
  }
 
2034
  logprintfl(EUCAINFO,"TerminateInstances(): called\n");
 
2035
  logprintfl(EUCADEBUG,"TerminateInstances(): params: userId=%s, instIdsLen=%d, firstInstId=%s\n", SP(ccMeta ? ccMeta->userId : "UNSET"), instIdsLen, SP(instIdsLen ? instIds[0] : "UNSET"));
 
2036
  
 
2037
  sem_mywait(RESCACHE);
 
2038
  memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache));
 
2039
  sem_mypost(RESCACHE);
 
2040
  
 
2041
 
 
2042
  for (i=0; i<instIdsLen; i++) {
 
2043
    instId = instIds[i];
 
2044
    rc = find_instanceCacheId(instId, &myInstance);
 
2045
    if (!rc) {
 
2046
      // found the instance in the cache
 
2047
      if (!strcmp(myInstance->state, "Pending") || !strcmp(myInstance->state, "Extant") || !strcmp(myInstance->state, "Unknown")) {
 
2048
        start = myInstance->ncHostIdx;
 
2049
        stop = start+1;
 
2050
      } else {
 
2051
        // instance is not in a terminatable state
 
2052
        start = 0;
 
2053
        stop = 0;
 
2054
        (*outStatus)[i] = 0;
 
2055
      }
 
2056
      
 
2057
      rc = free_instanceNetwork(myInstance->ccnet.privateMac, myInstance->ccnet.vlan, 1, 1);
 
2058
 
 
2059
      free(myInstance);
 
2060
    } else {
 
2061
      // instance is not in cache, try all resources
 
2062
      start = 0;
 
2063
      stop = 0;
 
2064
      (*outStatus)[i] = 0;      
 
2065
    }
 
2066
    
 
2067
    
 
2068
    done=0;
 
2069
    for (j=start; j<stop && !done; j++) {
 
2070
      if (resourceCacheLocal.resources[j].state == RESUP) {
 
2071
 
 
2072
        rc = ncClientCall(ccMeta, 0, NCCALL, resourceCacheLocal.resources[j].ncURL, "ncTerminateInstance", instId, &shutdownState, &previousState);
 
2073
        if (rc) {
 
2074
          (*outStatus)[i] = 1;
 
2075
          logprintfl(EUCAWARN, "TerminateInstances(): failed to terminate '%s': instance may not exist any longer\n", instId);
 
2076
          ret = 1;
 
2077
        } else {
 
2078
          (*outStatus)[i] = 0;
 
2079
          ret = 0;
 
2080
          done++;
 
2081
        }
 
2082
      }
 
2083
    }
 
2084
  }
 
2085
  
 
2086
  logprintfl(EUCADEBUG,"TerminateInstances(): done.\n");
 
2087
  
 
2088
  shawn();
 
2089
 
 
2090
  return(0);
 
2091
}
 
2092
 
 
2093
int setup_shared_buffer(void **buf, char *bufname, size_t bytes, sem_t **lock, char *lockname, int mode) {
 
2094
  int shd, rc, ret;
 
2095
  
 
2096
  // create a lock and grab it
 
2097
  *lock = sem_open(lockname, O_CREAT, 0644, 1);    
 
2098
  sem_wait(*lock);
 
2099
  ret=0;
 
2100
 
 
2101
  if (mode == SHARED_MEM) {
 
2102
    // set up shared memory segment for config
 
2103
    shd = shm_open(bufname, O_CREAT | O_RDWR | O_EXCL, 0644);
 
2104
    if (shd >= 0) {
 
2105
      // if this is the first process to create the config, init to 0
 
2106
      rc = ftruncate(shd, bytes);
 
2107
    } else {
 
2108
      shd = shm_open(bufname, O_CREAT | O_RDWR, 0644);
 
2109
    }
 
2110
    if (shd < 0) {
 
2111
      fprintf(stderr, "cannot initialize shared memory segment\n");
 
2112
      sem_post(*lock);
 
2113
      sem_close(*lock);
 
2114
      return(1);
 
2115
    }
 
2116
    *buf = mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_SHARED, shd, 0);
 
2117
  } else if (mode == SHARED_FILE) {
 
2118
    char *tmpstr, path[MAX_PATH];
 
2119
    struct stat mystat;
 
2120
    int fd;
 
2121
    
 
2122
    tmpstr = getenv(EUCALYPTUS_ENV_VAR_NAME);
 
2123
    if (!tmpstr) {
 
2124
      snprintf(path, MAX_PATH, "/var/lib/eucalyptus/CC/%s", bufname);
 
2125
    } else {
 
2126
      snprintf(path, MAX_PATH, "%s/var/lib/eucalyptus/CC/%s", tmpstr, bufname);
 
2127
    }
 
2128
    fd = open(path, O_RDWR | O_CREAT, 0600);
 
2129
    if (fd<0) {
 
2130
      fprintf(stderr, "ERROR: cannot open/create '%s' to set up mmapped buffer\n", path);
 
2131
      ret = 1;
 
2132
    } else {
 
2133
      mystat.st_size = 0;
 
2134
      rc = fstat(fd, &mystat);
 
2135
      // this is the check to make sure we're dealing with a valid prior config
 
2136
      if (mystat.st_size != bytes) {
 
2137
        rc = ftruncate(fd, bytes);
 
2138
      }
 
2139
      *buf = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
 
2140
      if (*buf == NULL) {
 
2141
        fprintf(stderr, "ERROR: cannot mmap fd\n");
 
2142
        ret = 1;
 
2143
      }
 
2144
      close(fd);
 
2145
    }
 
2146
  }
 
2147
  sem_post(*lock);
 
2148
  return(ret);
 
2149
}
 
2150
 
 
2151
int initialize(void) {
 
2152
  int rc, ret;
 
2153
 
 
2154
  ret=0;
 
2155
  rc = init_thread();
 
2156
  if (rc) {
 
2157
    ret=1;
 
2158
    logprintfl(EUCAERROR, "initialize(): cannot initialize thread\n");
 
2159
  }
 
2160
 
 
2161
  rc = init_localstate();
 
2162
  if (rc) {
 
2163
    ret = 1;
 
2164
    logprintfl(EUCAERROR, "initialize(): cannot initialize local state\n");
 
2165
  }
 
2166
 
 
2167
  rc = init_config();
 
2168
  if (rc) {
 
2169
    ret=1;
 
2170
    logprintfl(EUCAERROR, "initialize(): cannot initialize from configuration file\n");
 
2171
  }
 
2172
  
 
2173
  if (config->use_tunnels) {
 
2174
    rc = vnetInitTunnels(vnetconfig);
 
2175
    if (rc) {
 
2176
      logprintfl(EUCAERROR, "initialize(): cannot initialize tunnels\n");
 
2177
    }
 
2178
  }
 
2179
 
 
2180
  rc = init_pthreads();
 
2181
  if (rc) {
 
2182
    logprintfl(EUCAERROR, "initialize(): cannot initialize background threads\n");
 
2183
    ret = 1;
 
2184
  }
 
2185
 
 
2186
  if (!ret) {
 
2187
    // initialization went well, this thread is now initialized
 
2188
    init=1;
 
2189
  }
 
2190
  
 
2191
  return(ret);
 
2192
}
 
2193
 
 
2194
/* 
 
2195
   As of 1.6.2, the CC will start a background thread to poll its
 
2196
   collection of nodes.  This thread populates an in-memory cache of
 
2197
   instance and resource information that can be accessed via the
 
2198
   regular describeInstances and describeResources calls to the CC.
 
2199
   The purpose of this separation is to allow for a more scalable
 
2200
   framework where describe operations do not block on access to node
 
2201
   controllers.
 
2202
*/
 
2203
void *monitor_thread(void *in) {
 
2204
  int rc;
 
2205
  ncMetadata ccMeta;
 
2206
  ccMeta.correlationId = strdup("monitor");
 
2207
  ccMeta.userId = strdup("eucalyptus");
 
2208
  if (!ccMeta.correlationId || !ccMeta.userId) {
 
2209
    logprintfl(EUCAFATAL, "monitor_thread(): out of memory!\n");
 
2210
    unlock_exit(1);
 
2211
  }
 
2212
  
 
2213
  while(1) {
 
2214
    // set up default signal handler for this child process (for SIGTERM)
 
2215
    struct sigaction newsigact;
 
2216
    newsigact.sa_handler = SIG_DFL;
 
2217
    newsigact.sa_flags = 0;
 
2218
    sigemptyset(&newsigact.sa_mask);
 
2219
    sigprocmask(SIG_SETMASK, &newsigact.sa_mask, NULL);
 
2220
    sigaction(SIGTERM, &newsigact, NULL);
 
2221
 
 
2222
    logprintfl(EUCADEBUG, "monitor_thread(): running\n");
 
2223
 
 
2224
    rc = refresh_resources(&ccMeta, 60, 1);
 
2225
    if (rc) {
 
2226
      logprintfl(EUCAWARN, "monitor_thread(): call to refresh_resources() failed in monitor thread\n");
 
2227
    }
 
2228
    
 
2229
    rc = refresh_instances(&ccMeta, 60, 1);
 
2230
    if (rc) {
 
2231
      logprintfl(EUCAWARN, "monitor_thread(): call to refresh_instances() failed in monitor thread\n");
 
2232
    }
 
2233
 
 
2234
    sem_mywait(CONFIG);
 
2235
    if (config->kick_dhcp) {
 
2236
      rc = vnetKickDHCP(vnetconfig);
 
2237
      if (rc) {
 
2238
        logprintfl(EUCAERROR, "monitor_thread(): cannot start DHCP daemon\n");
 
2239
      } else {
 
2240
        config->kick_dhcp = 0;
 
2241
      }
 
2242
    }
 
2243
    sem_mypost(CONFIG);
 
2244
 
 
2245
    shawn();
 
2246
    
 
2247
    logprintfl(EUCADEBUG, "monitor_thread(): done\n");
 
2248
    sleep(config->ncPollingFrequency);
 
2249
  }
 
2250
  return(NULL);
 
2251
}
 
2252
 
 
2253
int init_pthreads() {
 
2254
  // start any background threads
 
2255
  if (!config_init) {
 
2256
    return(1);
 
2257
  }
 
2258
  sem_mywait(CONFIG);
 
2259
  if (config->threads[MONITOR] == 0 || check_process(config->threads[MONITOR], "httpd-cc.conf")) {
 
2260
    int pid;
 
2261
    pid = fork();
 
2262
    if (!pid) {
 
2263
      // set up default signal handler for this child process (for SIGTERM)
 
2264
      struct sigaction newsigact;
 
2265
      newsigact.sa_handler = SIG_DFL;
 
2266
      newsigact.sa_flags = 0;
 
2267
      sigemptyset(&newsigact.sa_mask);
 
2268
      sigprocmask(SIG_SETMASK, &newsigact.sa_mask, NULL);
 
2269
      sigaction(SIGTERM, &newsigact, NULL);
 
2270
 
 
2271
      monitor_thread(NULL);
 
2272
      exit(0);
 
2273
    } else {
 
2274
      config->threads[MONITOR] = pid;
 
2275
    }
 
2276
  }
 
2277
 
 
2278
  sem_mypost(CONFIG);
 
2279
 
 
2280
  return(0);
 
2281
}
 
2282
 
 
2283
int init_localstate(void) {
 
2284
  int rc, loglevel, ret;
 
2285
  char *tmpstr=NULL, logFile[MAX_PATH], configFiles[2][MAX_PATH], home[MAX_PATH], vfile[MAX_PATH];
 
2286
 
 
2287
  ret=0;
 
2288
  if (local_init) {
 
2289
  } else {
 
2290
    // thread is not initialized, run first time local state setup
 
2291
    bzero(logFile, MAX_PATH);
 
2292
    bzero(home, MAX_PATH);
 
2293
    bzero(configFiles[0], MAX_PATH);
 
2294
    bzero(configFiles[1], MAX_PATH);
 
2295
    
 
2296
    tmpstr = getenv(EUCALYPTUS_ENV_VAR_NAME);
 
2297
    if (!tmpstr) {
 
2298
      snprintf(home, MAX_PATH, "/");
 
2299
    } else {
 
2300
      snprintf(home, MAX_PATH, "%s", tmpstr);
 
2301
    }
 
2302
    
 
2303
    snprintf(configFiles[1], MAX_PATH, EUCALYPTUS_CONF_LOCATION, home);
 
2304
    snprintf(configFiles[0], MAX_PATH, EUCALYPTUS_CONF_OVERRIDE_LOCATION, home);
 
2305
    snprintf(logFile, MAX_PATH, "%s/var/log/eucalyptus/cc.log", home);  
 
2306
    
 
2307
    tmpstr = getConfString(configFiles, 2, "LOGLEVEL");
 
2308
    if (!tmpstr) {
 
2309
      loglevel = EUCADEBUG;
 
2310
    } else {
 
2311
      if (!strcmp(tmpstr,"DEBUG")) {loglevel=EUCADEBUG;}
 
2312
      else if (!strcmp(tmpstr,"INFO")) {loglevel=EUCAINFO;}
 
2313
      else if (!strcmp(tmpstr,"WARN")) {loglevel=EUCAWARN;}
 
2314
      else if (!strcmp(tmpstr,"ERROR")) {loglevel=EUCAERROR;}
 
2315
      else if (!strcmp(tmpstr,"FATAL")) {loglevel=EUCAFATAL;}
 
2316
      else {loglevel=EUCADEBUG;}
 
2317
    }
 
2318
    if (tmpstr) free(tmpstr);
 
2319
    // set up logfile
 
2320
    logfile(logFile, loglevel);
 
2321
    
 
2322
    local_init=1;
 
2323
  }
 
2324
 
 
2325
  return(ret);
 
2326
}
 
2327
 
 
2328
int init_thread(void) {
 
2329
  int rc;
 
2330
  
 
2331
  logprintfl(EUCADEBUG, "init_thread(): init=%d %08X %08X %08X %08X\n", init, config, vnetconfig, instanceCache, resourceCache);
 
2332
  if (thread_init) {
 
2333
    // thread has already been initialized
 
2334
  } else {
 
2335
    // this thread has not been initialized, set up shared memory segments
 
2336
    srand(time(NULL));
 
2337
 
 
2338
    locks[INIT] = sem_open("/eucalyptusCCinitLock", O_CREAT, 0644, 1);
 
2339
    sem_mywait(INIT);
 
2340
 
 
2341
    locks[NCCALL] = sem_open("/eucalyptusCCncCallLock", O_CREAT, 0644, 4);
 
2342
    
 
2343
    if (config == NULL) {
 
2344
      rc = setup_shared_buffer((void **)&config, "/eucalyptusCCConfig", sizeof(ccConfig), &(locks[CONFIG]), "/eucalyptusCCConfigLock", SHARED_FILE);
 
2345
      if (rc != 0) {
 
2346
        fprintf(stderr, "init_thread(): Cannot set up shared memory region for ccConfig, exiting...\n");
 
2347
        sem_mypost(INIT);
 
2348
        exit(1);
 
2349
      }
 
2350
    }
 
2351
    
 
2352
    if (instanceCache == NULL) {
 
2353
      rc = setup_shared_buffer((void **)&instanceCache, "/eucalyptusCCInstanceCache", sizeof(ccInstanceCache), &(locks[INSTCACHE]), "/eucalyptusCCInstanceCacheLock", SHARED_FILE);
 
2354
      if (rc != 0) {
 
2355
        fprintf(stderr, "init_thread(): Cannot set up shared memory region for ccInstanceCache, exiting...\n");
 
2356
        sem_mypost(INIT);
 
2357
        exit(1);
 
2358
      }
 
2359
    }
 
2360
 
 
2361
    if (resourceCache == NULL) {
 
2362
      rc = setup_shared_buffer((void **)&resourceCache, "/eucalyptusCCResourceCache", sizeof(ccResourceCache), &(locks[RESCACHE]), "/eucalyptusCCResourceCacheLock", SHARED_FILE);
 
2363
      if (rc != 0) {
 
2364
        fprintf(stderr, "init_thread(): Cannot set up shared memory region for ccResourceCache, exiting...\n");
 
2365
        sem_mypost(INIT);
 
2366
        exit(1);
 
2367
      }
 
2368
    }
 
2369
    
 
2370
    if (vnetconfig == NULL) {
 
2371
      rc = setup_shared_buffer((void **)&vnetconfig, "/eucalyptusCCVNETConfig", sizeof(vnetConfig), &(locks[VNET]), "/eucalyptusCCVNETConfigLock", SHARED_FILE);
 
2372
      if (rc != 0) {
 
2373
        fprintf(stderr, "init_thread(): Cannot set up shared memory region for ccVNETConfig, exiting...\n");
 
2374
        sem_mypost(INIT);
 
2375
        exit(1);
 
2376
      }
 
2377
    }
 
2378
 
 
2379
    sem_mypost(INIT);
 
2380
    thread_init=1;
 
2381
  }
 
2382
  return(0);
 
2383
}
 
2384
 
 
2385
int update_config(void) {
 
2386
  char home[MAX_PATH], *tmpstr=NULL;
 
2387
  ccResource *res=NULL;
 
2388
  int rc, numHosts, ret;
 
2389
  time_t configMtime;
 
2390
  struct stat statbuf;
 
2391
  int i;
 
2392
 
 
2393
  ret = 0;
 
2394
 
 
2395
  
 
2396
  configMtime = 0;
 
2397
  sem_mywait(CONFIG);
 
2398
  for (i=0; i<2; i++) {
 
2399
    // stat the config file, update modification time
 
2400
    rc = stat(config->configFiles[i], &statbuf);
 
2401
    if (!rc) {
 
2402
      if (statbuf.st_mtime > configMtime) {
 
2403
        configMtime = statbuf.st_mtime;
 
2404
      }
 
2405
    }
 
2406
  }
 
2407
  if (configMtime == 0) {
 
2408
    logprintfl(EUCAERROR, "update_config(): could not stat config files (%s,%s)\n", config->configFiles[0], config->configFiles[1]);
 
2409
    sem_mypost(CONFIG);
 
2410
    return(1);
 
2411
  }
 
2412
  
 
2413
  // check to see if the configfile has changed
 
2414
  if (config->configMtime != configMtime) {
 
2415
    // something has changed
 
2416
    logprintfl(EUCAINFO, "update_config(): config file has been modified, refreshing node list\n");
 
2417
    res = NULL;
 
2418
    rc = refreshNodes(config, &res, &numHosts);
 
2419
    if (rc) {
 
2420
      logprintfl(EUCAERROR, "update_config(): cannot read list of nodes, check your config file\n");
 
2421
      sem_mywait(RESCACHE);
 
2422
      resourceCache->numResources = 0;
 
2423
      config->schedState = 0;
 
2424
      bzero(resourceCache->resources, sizeof(ccResource) * MAXNODES);
 
2425
      sem_mypost(RESCACHE);
 
2426
      ret = 1;
 
2427
    } else {
 
2428
      sem_mywait(RESCACHE);
 
2429
      if (numHosts > MAXNODES) {
 
2430
        logprintfl(EUCAWARN, "update_config(): the list of nodes specified exceeds the maximum number of nodes that a single CC can support (%d).  Truncating list to %d nodes.\n", MAXNODES, MAXNODES);
 
2431
        numHosts = MAXNODES;
 
2432
      }
 
2433
      resourceCache->numResources = numHosts;
 
2434
      config->schedState = 0;
 
2435
      memcpy(resourceCache->resources, res, sizeof(ccResource) * numHosts);
 
2436
      sem_mypost(RESCACHE);
 
2437
    }
 
2438
    if (res) free(res);
 
2439
  }
 
2440
  
 
2441
  config->configMtime = configMtime;
 
2442
  sem_mypost(CONFIG);
 
2443
  
 
2444
  return(ret);
 
2445
}
 
2446
 
 
2447
int init_config(void) {
 
2448
  ccResource *res=NULL;
 
2449
  char *tmpstr=NULL;
 
2450
  int rc, numHosts, use_wssec, use_tunnels, schedPolicy, idleThresh, wakeThresh, ret, i;
 
2451
  
 
2452
  char configFiles[2][MAX_PATH], netPath[MAX_PATH], eucahome[MAX_PATH], policyFile[MAX_PATH], home[MAX_PATH];
 
2453
  
 
2454
  time_t configMtime, instanceTimeout, ncPollingFrequency;
 
2455
  struct stat statbuf;
 
2456
  
 
2457
  // read in base config information
 
2458
  tmpstr = getenv(EUCALYPTUS_ENV_VAR_NAME);
 
2459
  if (!tmpstr) {
 
2460
    snprintf(home, MAX_PATH, "/");
 
2461
  } else {
 
2462
    snprintf(home, MAX_PATH, "%s", tmpstr);
 
2463
  }
 
2464
  
 
2465
  bzero(configFiles[0], MAX_PATH);
 
2466
  bzero(configFiles[1], MAX_PATH);
 
2467
  bzero(netPath, MAX_PATH);
 
2468
  bzero(policyFile, MAX_PATH);
 
2469
  
 
2470
  snprintf(configFiles[1], MAX_PATH, EUCALYPTUS_CONF_LOCATION, home);
 
2471
  snprintf(configFiles[0], MAX_PATH, EUCALYPTUS_CONF_OVERRIDE_LOCATION, home);
 
2472
  snprintf(netPath, MAX_PATH, CC_NET_PATH_DEFAULT, home);
 
2473
  snprintf(policyFile, MAX_PATH, "%s/var/lib/eucalyptus/keys/nc-client-policy.xml", home);
 
2474
  snprintf(eucahome, MAX_PATH, "%s/", home);
 
2475
 
 
2476
  if (config_init && config->initialized) {
 
2477
    // this means that this thread has already been initialized
 
2478
    ret = 0;
 
2479
    return(ret);
 
2480
  }
 
2481
  
 
2482
  if (config->initialized) {
 
2483
    // some other thread has already initialized the configuration
 
2484
    logprintfl(EUCAINFO, "init_config():  another thread has already set up config, skipping\n");
 
2485
    rc = restoreNetworkState();
 
2486
    if (rc) {
 
2487
      // failed to restore network state, continue 
 
2488
      logprintfl(EUCAWARN, "init_config(): restoreNetworkState returned false (may be already restored)\n");
 
2489
    }
 
2490
    config_init = 1;
 
2491
    return(0);
 
2492
  }
 
2493
  
 
2494
  logprintfl(EUCADEBUG,"init_config(): initializing CC configuration\n");  
 
2495
  
 
2496
  // DHCP configuration section
 
2497
  {
 
2498
    char *daemon=NULL,
 
2499
      *dhcpuser=NULL,
 
2500
      *numaddrs=NULL,
 
2501
      *pubmode=NULL,
 
2502
      *pubmacmap=NULL,
 
2503
      *pubips=NULL,
 
2504
      *pubInterface=NULL,
 
2505
      *privInterface=NULL,
 
2506
      *pubSubnet=NULL,
 
2507
      *pubSubnetMask=NULL,
 
2508
      *pubBroadcastAddress=NULL,
 
2509
      *pubRouter=NULL,
 
2510
      *pubDNS=NULL,
 
2511
      *localIp=NULL,
 
2512
      *cloudIp=NULL;
 
2513
    uint32_t *ips, *nms;
 
2514
    int initFail=0, len;
 
2515
    
 
2516
    // DHCP Daemon Configuration Params
 
2517
    daemon = getConfString(configFiles, 2, "VNET_DHCPDAEMON");
 
2518
    if (!daemon) {
 
2519
      logprintfl(EUCAWARN,"init_config(): no VNET_DHCPDAEMON defined in config, using default\n");
 
2520
    }
 
2521
    
 
2522
    dhcpuser = getConfString(configFiles, 2, "VNET_DHCPUSER");
 
2523
    if (!dhcpuser) {
 
2524
      dhcpuser = strdup("root");
 
2525
      if (!dhcpuser) {
 
2526
         logprintfl(EUCAFATAL,"init_config(): Out of memory\n");
 
2527
         unlock_exit(1);
 
2528
      }
 
2529
    }
 
2530
    
 
2531
    pubmode = getConfString(configFiles, 2, "VNET_MODE");
 
2532
    if (!pubmode) {
 
2533
      logprintfl(EUCAWARN,"init_config(): VNET_MODE is not defined, defaulting to 'SYSTEM'\n");
 
2534
      pubmode = strdup("SYSTEM");
 
2535
      if (!pubmode) {
 
2536
         logprintfl(EUCAFATAL,"init_config(): Out of memory\n");
 
2537
         unlock_exit(1);
 
2538
      }
 
2539
    }
 
2540
    
 
2541
    {
 
2542
      int usednew=0;
 
2543
      
 
2544
      pubInterface = getConfString(configFiles, 2, "VNET_PUBINTERFACE");
 
2545
      if (!pubInterface) {
 
2546
        logprintfl(EUCAWARN,"init_config(): VNET_PUBINTERFACE is not defined, defaulting to 'eth0'\n");
 
2547
        pubInterface = strdup("eth0");
 
2548
        if (!pubInterface) {
 
2549
          logprintfl(EUCAFATAL, "init_config(): out of memory!\n");
 
2550
          unlock_exit(1);
 
2551
        }
 
2552
      } else {
 
2553
        usednew=1;
 
2554
      }
 
2555
      
 
2556
      privInterface = NULL;
 
2557
      privInterface = getConfString(configFiles, 2, "VNET_PRIVINTERFACE");
 
2558
      if (!privInterface) {
 
2559
        logprintfl(EUCAWARN,"init_config(): VNET_PRIVINTERFACE is not defined, defaulting to 'eth0'\n");
 
2560
        privInterface = strdup("eth0");
 
2561
        if (!privInterface) {
 
2562
          logprintfl(EUCAFATAL, "init_config(): out of memory!\n");
 
2563
          unlock_exit(1);
 
2564
        }
 
2565
        usednew = 0;
 
2566
      }
 
2567
      
 
2568
      if (!usednew) {
 
2569
        tmpstr = NULL;
 
2570
        tmpstr = getConfString(configFiles, 2, "VNET_INTERFACE");
 
2571
        if (tmpstr) {
 
2572
          logprintfl(EUCAWARN, "init_config(): VNET_INTERFACE is deprecated, please use VNET_PUBINTERFACE and VNET_PRIVINTERFACE instead.  Will set both to value of VNET_INTERFACE (%s) for now.\n", tmpstr);
 
2573
          if (pubInterface) free(pubInterface);
 
2574
          pubInterface = strdup(tmpstr);
 
2575
          if (!pubInterface) {
 
2576
            logprintfl(EUCAFATAL, "init_config(): out of memory!\n");
 
2577
            unlock_exit(1);
 
2578
          }
 
2579
 
 
2580
          if (privInterface) free(privInterface);
 
2581
          privInterface = strdup(tmpstr);
 
2582
          if (!privInterface) {
 
2583
            logprintfl(EUCAFATAL, "init_config(): out of memory!\n");
 
2584
            unlock_exit(1);
 
2585
          }
 
2586
        }
 
2587
        if (tmpstr) free(tmpstr);
 
2588
      }
 
2589
    }
 
2590
 
 
2591
    if (pubmode && !strcmp(pubmode, "STATIC")) {
 
2592
      pubSubnet = getConfString(configFiles, 2, "VNET_SUBNET");
 
2593
      pubSubnetMask = getConfString(configFiles, 2, "VNET_NETMASK");
 
2594
      pubBroadcastAddress = getConfString(configFiles, 2, "VNET_BROADCAST");
 
2595
      pubRouter = getConfString(configFiles, 2, "VNET_ROUTER");
 
2596
      pubDNS = getConfString(configFiles, 2, "VNET_DNS");
 
2597
      pubmacmap = getConfString(configFiles, 2, "VNET_MACMAP");
 
2598
 
 
2599
      if (!pubSubnet || !pubSubnetMask || !pubBroadcastAddress || !pubRouter || !pubDNS || !pubmacmap) {
 
2600
        logprintfl(EUCAFATAL,"init_config(): in 'STATIC' network mode, you must specify values for 'VNET_SUBNET, VNET_NETMASK, VNET_BROADCAST, VNET_ROUTER, VNET_DNS, and VNET_MACMAP'\n");
 
2601
        initFail = 1;
 
2602
      }
 
2603
    } else if (pubmode && (!strcmp(pubmode, "MANAGED") || !strcmp(pubmode, "MANAGED-NOVLAN"))) {
 
2604
      numaddrs = getConfString(configFiles, 2, "VNET_ADDRSPERNET");
 
2605
      pubSubnet = getConfString(configFiles, 2, "VNET_SUBNET");
 
2606
      pubSubnetMask = getConfString(configFiles, 2, "VNET_NETMASK");
 
2607
      pubDNS = getConfString(configFiles, 2, "VNET_DNS");
 
2608
      pubips = getConfString(configFiles, 2, "VNET_PUBLICIPS");
 
2609
      localIp = getConfString(configFiles, 2, "VNET_LOCALIP");
 
2610
      if (!localIp) {
 
2611
        logprintfl(EUCAWARN, "init_config(): VNET_LOCALIP not defined, will attempt to auto-discover (consider setting this explicitly if tunnelling does not function properly.)\n");
 
2612
      }
 
2613
      cloudIp = getConfString(configFiles, 2, "VNET_CLOUDIP");
 
2614
 
 
2615
      if (!pubSubnet || !pubSubnetMask || !pubDNS || !numaddrs) {
 
2616
        logprintfl(EUCAFATAL,"init_config(): in 'MANAGED' or 'MANAGED-NOVLAN' network mode, you must specify values for 'VNET_SUBNET, VNET_NETMASK, VNET_ADDRSPERNET, and VNET_DNS'\n");
 
2617
        initFail = 1;
 
2618
      }
 
2619
    }
 
2620
    
 
2621
    if (initFail) {
 
2622
      logprintfl(EUCAFATAL, "init_config(): bad network parameters, must fix before system will work\n");
 
2623
      if (cloudIp) free(cloudIp);
 
2624
      if (pubSubnet) free(pubSubnet);
 
2625
      if (pubSubnetMask) free(pubSubnetMask);
 
2626
      if (pubBroadcastAddress) free(pubBroadcastAddress);
 
2627
      if (pubRouter) free(pubRouter);
 
2628
      if (pubDNS) free(pubDNS);
 
2629
      if (pubmacmap) free(pubmacmap);
 
2630
      if (numaddrs) free(numaddrs);
 
2631
      if (pubips) free(pubips);
 
2632
      if (localIp) free(localIp);
 
2633
      if (pubInterface) free(pubInterface);
 
2634
      if (privInterface) free(privInterface);
 
2635
      if (dhcpuser) free(dhcpuser);
 
2636
      if (daemon) free(daemon);
 
2637
      if (pubmode) free(pubmode);
 
2638
      return(1);
 
2639
    }
 
2640
    
 
2641
    sem_mywait(VNET);
 
2642
    
 
2643
    vnetInit(vnetconfig, pubmode, eucahome, netPath, CLC, pubInterface, privInterface, numaddrs, pubSubnet, pubSubnetMask, pubBroadcastAddress, pubDNS, pubRouter, daemon, dhcpuser, NULL, localIp, cloudIp);
 
2644
    if (cloudIp) free(cloudIp);
 
2645
    if (pubSubnet) free(pubSubnet);
 
2646
    if (pubSubnetMask) free(pubSubnetMask);
 
2647
    if (pubBroadcastAddress) free(pubBroadcastAddress);
 
2648
    if (pubDNS) free(pubDNS);
 
2649
    if (pubRouter) free(pubRouter);
 
2650
    if (numaddrs) free(numaddrs);
 
2651
    if (pubmode) free(pubmode);
 
2652
    if (dhcpuser) free(dhcpuser);
 
2653
    if (daemon) free(daemon);
 
2654
    if (privInterface) free(privInterface);
 
2655
    if (pubInterface) free(pubInterface);
 
2656
    
 
2657
    vnetAddDev(vnetconfig, vnetconfig->privInterface);
 
2658
 
 
2659
    if (pubmacmap) {
 
2660
      char *mac=NULL, *ip=NULL, *ptra=NULL, *toka=NULL, *ptrb=NULL;
 
2661
      toka = strtok_r(pubmacmap, " ", &ptra);
 
2662
      while(toka) {
 
2663
        mac = ip = NULL;
 
2664
        mac = strtok_r(toka, "=", &ptrb);
 
2665
        ip = strtok_r(NULL, "=", &ptrb);
 
2666
        if (mac && ip) {
 
2667
          vnetAddHost(vnetconfig, mac, ip, 0, -1);
 
2668
        }
 
2669
        toka = strtok_r(NULL, " ", &ptra);
 
2670
      }
 
2671
      vnetKickDHCP(vnetconfig);
 
2672
      free(pubmacmap);
 
2673
    } else if (pubips) {
 
2674
      char *ip, *ptra, *toka;
 
2675
      toka = strtok_r(pubips, " ", &ptra);
 
2676
      while(toka) {
 
2677
        ip = toka;
 
2678
        if (ip) {
 
2679
          rc = vnetAddPublicIP(vnetconfig, ip);
 
2680
          if (rc) {
 
2681
            logprintfl(EUCAERROR, "init_config(): could not add public IP '%s'\n", ip);
 
2682
          }
 
2683
        }
 
2684
        toka = strtok_r(NULL, " ", &ptra);
 
2685
      }
 
2686
 
 
2687
      // detect and populate ips
 
2688
      if (vnetCountLocalIP(vnetconfig) <= 0) {
 
2689
        ips = nms = NULL;
 
2690
        rc = getdevinfo("all", &ips, &nms, &len);
 
2691
        if (!rc) {
 
2692
          for (i=0; i<len; i++) {
 
2693
            char *theip=NULL;
 
2694
            theip = hex2dot(ips[i]);
 
2695
            if (vnetCheckPublicIP(vnetconfig, theip)) {
 
2696
              vnetAddLocalIP(vnetconfig, ips[i]);
 
2697
            }
 
2698
            if (theip) free(theip);
 
2699
          }
 
2700
        }
 
2701
        if (ips) free(ips);
 
2702
        if (nms) free(nms);
 
2703
      }
 
2704
      free(pubips);
 
2705
    }
 
2706
    
 
2707
    sem_mypost(VNET);
 
2708
  }
 
2709
  
 
2710
  tmpstr = getConfString(configFiles, 2, "SCHEDPOLICY");
 
2711
  if (!tmpstr) {
 
2712
    // error
 
2713
    logprintfl(EUCAWARN,"init_config(): parsing config file (%s) for SCHEDPOLICY, defaulting to GREEDY\n", configFiles[0]);
 
2714
    schedPolicy = SCHEDGREEDY;
 
2715
    tmpstr = NULL;
 
2716
  } else {
 
2717
    if (!strcmp(tmpstr, "GREEDY")) schedPolicy = SCHEDGREEDY;
 
2718
    else if (!strcmp(tmpstr, "ROUNDROBIN")) schedPolicy = SCHEDROUNDROBIN;
 
2719
    else if (!strcmp(tmpstr, "POWERSAVE")) schedPolicy = SCHEDPOWERSAVE;
 
2720
    else schedPolicy = SCHEDGREEDY;
 
2721
  }
 
2722
  if (tmpstr) free(tmpstr);
 
2723
 
 
2724
  // powersave options
 
2725
  tmpstr = getConfString(configFiles, 2, "POWER_IDLETHRESH");
 
2726
  if (!tmpstr) {
 
2727
    logprintfl(EUCAWARN,"init_config(): parsing config file (%s) for POWER_IDLETHRESH, defaulting to 300 seconds\n", configFiles[0]);
 
2728
    idleThresh = 300;
 
2729
    tmpstr = NULL;
 
2730
  } else {
 
2731
    idleThresh = atoi(tmpstr);
 
2732
    if (idleThresh < 300) {
 
2733
      logprintfl(EUCAWARN, "init_config(): POWER_IDLETHRESH set too low (%d seconds), resetting to minimum (300 seconds)\n", idleThresh);
 
2734
      idleThresh = 300;
 
2735
    }
 
2736
  }
 
2737
  if (tmpstr) free(tmpstr);
 
2738
 
 
2739
  tmpstr = getConfString(configFiles, 2, "POWER_WAKETHRESH");
 
2740
  if (!tmpstr) {
 
2741
    logprintfl(EUCAWARN,"init_config(): parsing config file (%s) for POWER_WAKETHRESH, defaulting to 300 seconds\n", configFiles[0]);
 
2742
    wakeThresh = 300;
 
2743
    tmpstr = NULL;
 
2744
  } else {
 
2745
    wakeThresh = atoi(tmpstr);
 
2746
    if (wakeThresh < 300) {
 
2747
      logprintfl(EUCAWARN, "init_config(): POWER_WAKETHRESH set too low (%d seconds), resetting to minimum (300 seconds)\n", wakeThresh);
 
2748
      wakeThresh = 300;
 
2749
    }
 
2750
  }
 
2751
  if (tmpstr) free(tmpstr);
 
2752
 
 
2753
  // some administrative options
 
2754
  tmpstr = getConfString(configFiles, 2, "NC_POLLING_FREQUENCY");
 
2755
  if (!tmpstr) {
 
2756
    ncPollingFrequency = 6;
 
2757
    tmpstr = NULL;
 
2758
  } else {
 
2759
    ncPollingFrequency = atoi(tmpstr);
 
2760
    if (ncPollingFrequency < 6) {
 
2761
      logprintfl(EUCAWARN, "init_config(): NC_POLLING_FREQUENCY set too low (%d seconds), resetting to minimum (6 seconds)\n", ncPollingFrequency);
 
2762
      ncPollingFrequency = 6;
 
2763
    }
 
2764
  }
 
2765
  if (tmpstr) free(tmpstr);
 
2766
 
 
2767
  tmpstr = getConfString(configFiles, 2, "INSTANCE_TIMEOUT");
 
2768
  if (!tmpstr) {
 
2769
    instanceTimeout = 300;
 
2770
    tmpstr = NULL;
 
2771
  } else {
 
2772
    instanceTimeout = atoi(tmpstr);
 
2773
    if (instanceTimeout < 30) {
 
2774
      logprintfl(EUCAWARN, "init_config(): INSTANCE_TIMEOUT set too low (%d seconds), resetting to minimum (30 seconds)\n", instanceTimeout);
 
2775
      instanceTimeout = 30;
 
2776
    }
 
2777
  }
 
2778
  if (tmpstr) free(tmpstr);
 
2779
 
 
2780
  // WS-Security
 
2781
  use_wssec = 0;
 
2782
  tmpstr = getConfString(configFiles, 2, "ENABLE_WS_SECURITY");
 
2783
  if (!tmpstr) {
 
2784
    // error
 
2785
    logprintfl(EUCAFATAL,"init_config(): parsing config file (%s) for ENABLE_WS_SECURITY\n", configFiles[0]);
 
2786
    return(1);
 
2787
  } else {
 
2788
    if (!strcmp(tmpstr, "Y")) {
 
2789
      use_wssec = 1;
 
2790
    }
 
2791
  }
 
2792
  if (tmpstr) free(tmpstr);
 
2793
 
 
2794
  // Multi-cluster tunneling
 
2795
  use_tunnels = 1;
 
2796
  tmpstr = getConfString(configFiles, 2, "DISABLE_TUNNELING");
 
2797
  if (tmpstr) {
 
2798
    if (!strcmp(tmpstr, "Y")) {
 
2799
      use_tunnels = 0;
 
2800
    }
 
2801
  }
 
2802
  if (tmpstr) free(tmpstr);
 
2803
 
 
2804
  sem_mywait(CONFIG);
 
2805
  // set up the current config   
 
2806
  strncpy(config->eucahome, eucahome, MAX_PATH);
 
2807
  strncpy(config->policyFile, policyFile, MAX_PATH);
 
2808
  config->use_wssec = use_wssec;
 
2809
  config->use_tunnels = use_tunnels;
 
2810
  config->schedPolicy = schedPolicy;
 
2811
  config->idleThresh = idleThresh;
 
2812
  config->wakeThresh = wakeThresh;
 
2813
  //  config->configMtime = configMtime;
 
2814
  config->instanceTimeout = instanceTimeout;
 
2815
  config->ncPollingFrequency = ncPollingFrequency;
 
2816
  config->initialized = 1;
 
2817
  snprintf(config->configFiles[0], MAX_PATH, "%s", configFiles[0]);
 
2818
  snprintf(config->configFiles[1], MAX_PATH, "%s", configFiles[1]);
 
2819
  
 
2820
  logprintfl(EUCAINFO, "init_config(): CC Configuration: eucahome=%s, policyfile=%s, ws-security=%s, schedulerPolicy=%s, idleThreshold=%d, wakeThreshold=%d\n", SP(config->eucahome), SP(config->policyFile), use_wssec ? "ENABLED" : "DISABLED", SP(SCHEDPOLICIES[config->schedPolicy]), config->idleThresh, config->wakeThresh);
 
2821
 
 
2822
  sem_mypost(CONFIG);
 
2823
 
 
2824
  res = NULL;
 
2825
  rc = refreshNodes(config, &res, &numHosts);
 
2826
  if (rc) {
 
2827
    logprintfl(EUCAERROR, "init_config(): cannot read list of nodes, check your config file\n");
 
2828
    return(1);
 
2829
  }
 
2830
      
 
2831
  // update resourceCache
 
2832
  sem_mywait(RESCACHE);
 
2833
  resourceCache->numResources = numHosts;
 
2834
  if (numHosts) {
 
2835
    memcpy(resourceCache->resources, res, sizeof(ccResource) * numHosts);
 
2836
  }
 
2837
  if (res) free(res);
 
2838
  resourceCache->lastResourceUpdate = 0;
 
2839
  sem_mypost(RESCACHE);
 
2840
  
 
2841
  config_init=1;
 
2842
  logprintfl(EUCADEBUG,"init_config(): done\n");
 
2843
  
 
2844
  return(0);
 
2845
}
 
2846
 
 
2847
int maintainNetworkState() {
 
2848
  int rc, i, ret=0;
 
2849
  time_t startTime, startTimeA;
 
2850
 
 
2851
  if (!strcmp(vnetconfig->mode, "MANAGED") || !strcmp(vnetconfig->mode, "MANAGED-NOVLAN")) {
 
2852
    sem_mywait(VNET);
 
2853
    
 
2854
    rc = vnetSetupTunnels(vnetconfig);
 
2855
 
 
2856
    if (rc) {
 
2857
      logprintfl(EUCAERROR, "maintainNetworkState(): failed to setup tunnels during maintainNetworkState()\n");
 
2858
      ret = 1;
 
2859
    }
 
2860
    
 
2861
    for (i=2; i<NUMBER_OF_VLANS; i++) {
 
2862
      if (vnetconfig->networks[i].active) {
 
2863
        char brname[32];
 
2864
        if (!strcmp(vnetconfig->mode, "MANAGED")) {
 
2865
          snprintf(brname, 32, "eucabr%d", i);
 
2866
        } else {
 
2867
          snprintf(brname, 32, "%s", vnetconfig->privInterface);
 
2868
        }
 
2869
        startTime=time(NULL);
 
2870
        rc = vnetAttachTunnels(vnetconfig, i, brname);
 
2871
        if (rc) {
 
2872
          logprintfl(EUCADEBUG, "maintainNetworkState(): failed to attach tunnels for vlan %d during maintainNetworkState()\n", i);
 
2873
          ret = 1;
 
2874
        }
 
2875
      }
 
2876
    }
 
2877
    sem_mypost(VNET);
 
2878
  }
 
2879
  
 
2880
  return(ret);
 
2881
}
 
2882
 
 
2883
int restoreNetworkState() {
 
2884
  int rc, ret=0, i;
 
2885
  char cmd[MAX_PATH];
 
2886
 
 
2887
  logprintfl(EUCADEBUG, "restoreNetworkState(): restoring network state\n");
 
2888
  sem_mywait(VNET);
 
2889
 
 
2890
  // restore iptables state                                                                                    
 
2891
  logprintfl(EUCADEBUG, "restoreNetworkState(): restarting iptables\n");
 
2892
  rc = vnetRestoreTablesFromMemory(vnetconfig);
 
2893
  if (rc) {
 
2894
    logprintfl(EUCAERROR, "restoreNetworkState(): cannot restore iptables state\n");
 
2895
    ret = 1;
 
2896
  }
 
2897
  
 
2898
  // restore ip addresses                                                                                      
 
2899
  logprintfl(EUCADEBUG, "restoreNetworkState(): restarting ips\n");
 
2900
  if (!strcmp(vnetconfig->mode, "MANAGED") || !strcmp(vnetconfig->mode, "MANAGED-NOVLAN")) {
 
2901
    snprintf(cmd, MAX_PATH, "%s/usr/lib/eucalyptus/euca_rootwrap ip addr add 169.254.169.254/32 scope link dev %s", config->eucahome, vnetconfig->privInterface);
 
2902
    logprintfl(EUCADEBUG,"restoreNetworkState(): running cmd %s\n", cmd);
 
2903
    rc = system(cmd);
 
2904
    if (rc) {
 
2905
      logprintfl(EUCAWARN, "restoreNetworkState(): cannot add ip 169.254.169.254\n");
 
2906
    }
 
2907
  }
 
2908
  for (i=1; i<NUMBER_OF_PUBLIC_IPS; i++) {
 
2909
    if (vnetconfig->publicips[i].allocated) {
 
2910
      char *tmp;
 
2911
 
 
2912
      tmp = hex2dot(vnetconfig->publicips[i].ip);
 
2913
      snprintf(cmd, MAX_PATH, "%s/usr/lib/eucalyptus/euca_rootwrap ip addr add %s/32 dev %s", config->eucahome, tmp, vnetconfig->pubInterface);
 
2914
      logprintfl(EUCADEBUG,"restoreNetworkState(): running cmd %s\n", cmd);
 
2915
      rc = system(cmd);
 
2916
      if (rc) {
 
2917
        logprintfl(EUCAWARN, "restoreNetworkState(): cannot add ip %s\n", tmp);
 
2918
      }
 
2919
      free(tmp);
 
2920
    }
 
2921
  }
 
2922
 
 
2923
  // re-create all active networks
 
2924
  logprintfl(EUCADEBUG, "restoreNetworkState(): restarting networks\n");
 
2925
  for (i=2; i<NUMBER_OF_VLANS; i++) {
 
2926
    if (vnetconfig->networks[i].active) {
 
2927
      char *brname=NULL;
 
2928
      logprintfl(EUCADEBUG, "restoreNetworkState(): found active network: %d\n", i);
 
2929
      rc = vnetStartNetwork(vnetconfig, i, vnetconfig->users[i].userName, vnetconfig->users[i].netName, &brname);
 
2930
      if (rc) {
 
2931
        logprintfl(EUCADEBUG, "restoreNetworkState(): failed to reactivate network: %d", i);
 
2932
      }
 
2933
      if (brname) free(brname);
 
2934
    }
 
2935
  }
 
2936
  // get DHCPD back up and running
 
2937
  logprintfl(EUCADEBUG, "restoreNetworkState(): restarting DHCPD\n");
 
2938
  rc = vnetKickDHCP(vnetconfig);
 
2939
  if (rc) {
 
2940
    logprintfl(EUCAERROR, "restoreNetworkState(): cannot start DHCP daemon, please check your network settings\n");
 
2941
    ret = 1;
 
2942
  }
 
2943
  sem_mypost(VNET);
 
2944
  logprintfl(EUCADEBUG, "restoreNetworkState(): done restoring network state\n");
 
2945
 
 
2946
  return(ret);
 
2947
}
 
2948
 
 
2949
int refreshNodes(ccConfig *config, ccResource **res, int *numHosts) {
 
2950
  int rc, i;
 
2951
  char *tmpstr, *ipbuf;
 
2952
  char ncservice[512];
 
2953
  int ncport;
 
2954
  char **hosts;
 
2955
 
 
2956
  *numHosts = 0;
 
2957
  *res = NULL;
 
2958
 
 
2959
  tmpstr = getConfString(config->configFiles, 2, CONFIG_NC_SERVICE);
 
2960
  if (!tmpstr) {
 
2961
    // error
 
2962
    logprintfl(EUCAFATAL,"refreshNodes(): parsing config files (%s,%s) for NC_SERVICE\n", config->configFiles[1], config->configFiles[0]);
 
2963
    return(1);
 
2964
  } else {
 
2965
    if(tmpstr) {
 
2966
      snprintf(ncservice, 512, "%s", tmpstr);
 
2967
    }
 
2968
 
 
2969
  }
 
2970
  if (tmpstr) free(tmpstr);
 
2971
 
 
2972
  tmpstr = getConfString(config->configFiles, 2, CONFIG_NC_PORT);
 
2973
  if (!tmpstr) {
 
2974
    // error
 
2975
    logprintfl(EUCAFATAL,"refreshNodes(): parsing config files (%s,%s) for NC_PORT\n", config->configFiles[1], config->configFiles[0]);
 
2976
    return(1);
 
2977
  } else {
 
2978
    if(tmpstr)
 
2979
      ncport = atoi(tmpstr);
 
2980
  }
 
2981
  if (tmpstr) free(tmpstr);
 
2982
 
 
2983
  tmpstr = getConfString(config->configFiles, 2, CONFIG_NODES);
 
2984
  if (!tmpstr) {
 
2985
    // error
 
2986
    logprintfl(EUCAWARN,"refreshNodes(): NODES parameter is missing from config files(%s,%s)\n", config->configFiles[1], config->configFiles[0]);
 
2987
    return(0);
 
2988
  } else {
 
2989
    hosts = from_var_to_char_list(tmpstr);
 
2990
    if (hosts == NULL) {
 
2991
      logprintfl(EUCAWARN,"refreshNodes(): NODES list is empty in config files(%s,%s)\n", config->configFiles[1], config->configFiles[0]);
 
2992
      if (tmpstr) free(tmpstr);
 
2993
      return(0);
 
2994
    }
 
2995
 
 
2996
    *numHosts = 0;
 
2997
    i = 0;
 
2998
    while(hosts[i] != NULL) {
 
2999
      (*numHosts)++;
 
3000
      *res = realloc(*res, sizeof(ccResource) * *numHosts);
 
3001
      bzero(&((*res)[*numHosts-1]), sizeof(ccResource));
 
3002
      snprintf((*res)[*numHosts-1].hostname, 128, "%s", hosts[i]);
 
3003
 
 
3004
      ipbuf = host2ip(hosts[i]);
 
3005
      if (ipbuf) {
 
3006
        snprintf((*res)[*numHosts-1].ip, 24, "%s", ipbuf);
 
3007
      }
 
3008
      if (ipbuf) free(ipbuf);
 
3009
 
 
3010
      (*res)[*numHosts-1].ncPort = ncport;
 
3011
      snprintf((*res)[*numHosts-1].ncService, 128, "%s", ncservice);
 
3012
      snprintf((*res)[*numHosts-1].ncURL, 128, "http://%s:%d/%s", hosts[i], ncport, ncservice); 
 
3013
      (*res)[*numHosts-1].state = RESDOWN;
 
3014
      (*res)[*numHosts-1].lastState = RESDOWN;
 
3015
      free(hosts[i]);
 
3016
      i++;
 
3017
    }
 
3018
  }
 
3019
  if (hosts) free(hosts);
 
3020
  if (tmpstr) free(tmpstr);
 
3021
  return(0);
 
3022
}
 
3023
 
 
3024
void shawn() {
 
3025
  int p=1, status, rc;
 
3026
 
 
3027
  // clean up any orphaned child processes
 
3028
  while(p > 0) {
 
3029
    p = waitpid(-1, &status, WNOHANG);
 
3030
  }
 
3031
  
 
3032
  rc = maintainNetworkState();
 
3033
  if (rc) {
 
3034
    logprintfl(EUCAERROR, "shawn(): network state maintainance failed\n");
 
3035
  }
 
3036
  
 
3037
  if (instanceCache) msync(instanceCache, sizeof(ccInstanceCache), MS_ASYNC);
 
3038
  if (resourceCache) msync(resourceCache, sizeof(ccResourceCache), MS_ASYNC);
 
3039
  if (config) msync(config, sizeof(ccConfig), MS_ASYNC);
 
3040
  if (vnetconfig) msync(vnetconfig, sizeof(vnetConfig), MS_ASYNC);
 
3041
 
 
3042
}
 
3043
 
 
3044
int timeread(int fd, void *buf, size_t bytes, int timeout) {
 
3045
  int rc;
 
3046
  fd_set rfds;
 
3047
  struct timeval tv;
 
3048
 
 
3049
  if (timeout <= 0) timeout = 1;
 
3050
 
 
3051
  FD_ZERO(&rfds);
 
3052
  FD_SET(fd, &rfds);
 
3053
  
 
3054
  tv.tv_sec = timeout;
 
3055
  tv.tv_usec = 0;
 
3056
  
 
3057
  rc = select(fd+1, &rfds, NULL, NULL, &tv);
 
3058
  if (rc <= 0) {
 
3059
    // timeout
 
3060
    logprintfl(EUCAERROR, "timeread(): select() timed out for read: timeout=%d\n", timeout);
 
3061
    return(-1);
 
3062
  }
 
3063
  rc = read(fd, buf, bytes);
 
3064
  return(rc);
 
3065
}
 
3066
 
 
3067
int allocate_ccResource(ccResource *out, char *ncURL, char *ncService, int ncPort, char *hostname, char *mac, char *ip, int maxMemory, int availMemory, int maxDisk, int availDisk, int maxCores, int availCores, int state, int laststate, time_t stateChange, time_t idleStart) {
 
3068
 
 
3069
  if (out != NULL) {
 
3070
    if (ncURL) strncpy(out->ncURL, ncURL, 128);
 
3071
    if (ncService) strncpy(out->ncService, ncService, 128);
 
3072
    if (hostname) strncpy(out->hostname, hostname, 128);
 
3073
    if (mac) strncpy(out->mac, mac, 24);
 
3074
    if (ip) strncpy(out->ip, ip, 24);
 
3075
    
 
3076
    out->ncPort = ncPort;
 
3077
    out->maxMemory = maxMemory;
 
3078
    out->availMemory = availMemory;
 
3079
    out->maxDisk = maxDisk;
 
3080
    out->availDisk = availDisk;
 
3081
    out->maxCores = maxCores;
 
3082
    out->availCores = availCores;
 
3083
    out->state = state;
 
3084
    out->lastState = laststate;
 
3085
    out->stateChange = stateChange;
 
3086
    out->idleStart = idleStart;
 
3087
  }
 
3088
 
 
3089
  return(0);
 
3090
}
 
3091
 
 
3092
int free_instanceNetwork(char *mac, int vlan, int force, int dolock) {
 
3093
  int inuse, i;
 
3094
  unsigned char hexmac[6];
 
3095
  mac2hex(mac, hexmac);
 
3096
  if (!maczero(hexmac)) {
 
3097
    return(0);
 
3098
  }
 
3099
 
 
3100
  if (dolock) {
 
3101
    sem_mywait(INSTCACHE);
 
3102
  }
 
3103
 
 
3104
  inuse=0;
 
3105
  if (!force) {
 
3106
    // check to make sure the mac isn't in use elsewhere
 
3107
    for (i=0; i<MAXINSTANCES && !inuse; i++) {
 
3108
      if (!strcmp(instanceCache->instances[i].ccnet.privateMac, mac) && strcmp(instanceCache->instances[i].state, "Teardown")) {
 
3109
        inuse++;
 
3110
      }
 
3111
    }
 
3112
  }
 
3113
 
 
3114
  if (dolock) {
 
3115
    sem_mypost(INSTCACHE);
 
3116
  }
 
3117
 
 
3118
  if (!inuse) {
 
3119
    // remove private network info from system                                                                                                                                                                
 
3120
    sem_mywait(VNET);
 
3121
    vnetDisableHost(vnetconfig, mac, NULL, 0);
 
3122
    if (!strcmp(vnetconfig->mode, "MANAGED") || !strcmp(vnetconfig->mode, "MANAGED-NOVLAN")) {
 
3123
      vnetDelHost(vnetconfig, mac, NULL, vlan);
 
3124
    }
 
3125
    sem_mypost(VNET);
 
3126
  }
 
3127
  return(0);
 
3128
}
 
3129
 
 
3130
int allocate_ccInstance(ccInstance *out, char *id, char *amiId, char *kernelId, char *ramdiskId, char *amiURL, char *kernelURL, char *ramdiskURL, char *ownerId, char *state, time_t ts, char *reservationId, netConfig *ccnet, virtualMachine *ccvm, int ncHostIdx, char *keyName, char *serviceTag, char *userData, char *launchIndex, char groupNames[][32], ncVolume *volumes, int volumesSize) {
 
3131
  if (out != NULL) {
 
3132
    bzero(out, sizeof(ccInstance));
 
3133
    if (id) strncpy(out->instanceId, id, 16);
 
3134
    if (amiId) strncpy(out->amiId, amiId, 16);
 
3135
    if (kernelId) strncpy(out->kernelId, kernelId, 16);
 
3136
    if (ramdiskId) strncpy(out->ramdiskId, ramdiskId, 16);
 
3137
    
 
3138
    if (amiURL) strncpy(out->amiURL, amiURL, 512);
 
3139
    if (kernelURL) strncpy(out->kernelURL, kernelURL, 512);
 
3140
    if (ramdiskURL) strncpy(out->ramdiskURL, ramdiskURL, 512);
 
3141
    
 
3142
    if (state) strncpy(out->state, state, 16);
 
3143
    if (ownerId) strncpy(out->ownerId, ownerId, 16);
 
3144
    if (reservationId) strncpy(out->reservationId, reservationId, 16);
 
3145
    if (keyName) strncpy(out->keyName, keyName, 1024);
 
3146
    out->ts = ts;
 
3147
    out->ncHostIdx = ncHostIdx;
 
3148
    if (serviceTag) strncpy(out->serviceTag, serviceTag, 64);
 
3149
    if (userData) strncpy(out->userData, userData, 4096);
 
3150
    if (launchIndex) strncpy(out->launchIndex, launchIndex, 64);
 
3151
    if (groupNames) {
 
3152
      int i;
 
3153
      for (i=0; i<64; i++) {
 
3154
        if (groupNames[i]) {
 
3155
          strncpy(out->groupNames[i], groupNames[i], 32);
 
3156
        }
 
3157
      }
 
3158
    }
 
3159
 
 
3160
    if (volumes) {
 
3161
      memcpy(out->volumes, volumes, sizeof(ncVolume) * EUCA_MAX_VOLUMES);
 
3162
    }
 
3163
    out->volumesSize = volumesSize;
 
3164
    //    if (networkIndex) out->networkIndex = networkIndex;
 
3165
 
 
3166
    if (ccnet) allocate_netConfig(&(out->ccnet), ccnet->privateMac, ccnet->privateIp, ccnet->publicIp, ccnet->vlan, ccnet->networkIndex);
 
3167
    if (ccvm) allocate_virtualMachine(&(out->ccvm), ccvm);
 
3168
  }
 
3169
  return(0);
 
3170
}
 
3171
 
 
3172
int pubIpCmp(ccInstance *inst, void *ip) {
 
3173
  if (!ip || !inst) {
 
3174
    return(1);
 
3175
  }
 
3176
  
 
3177
  if (!strcmp((char *)ip, inst->ccnet.publicIp)) {
 
3178
    return(0);
 
3179
  }
 
3180
  return(1);
 
3181
}
 
3182
 
 
3183
int privIpCmp(ccInstance *inst, void *ip) {
 
3184
  if (!ip || !inst) {
 
3185
    return(1);
 
3186
  }
 
3187
  
 
3188
  if (!strcmp((char *)ip, inst->ccnet.privateIp)) {
 
3189
    return(0);
 
3190
  }
 
3191
  return(1);
 
3192
}
 
3193
 
 
3194
int privIpSet(ccInstance *inst, void *ip) {
 
3195
  if (!ip || !inst) {
 
3196
    return(1);
 
3197
  }
 
3198
  
 
3199
  logprintfl(EUCADEBUG, "privIpSet(): set: %s/%s\n", inst->ccnet.privateIp, (char *)ip);
 
3200
  snprintf(inst->ccnet.privateIp, 24, "%s", (char *)ip);
 
3201
  return(0);
 
3202
}
 
3203
 
 
3204
int pubIpSet(ccInstance *inst, void *ip) {
 
3205
  if (!ip || !inst) {
 
3206
    return(1);
 
3207
  }
 
3208
  
 
3209
  logprintfl(EUCADEBUG, "pubIpSet(): set: %s/%s\n", inst->ccnet.publicIp, (char *)ip);
 
3210
  snprintf(inst->ccnet.publicIp, 24, "%s", (char *)ip);
 
3211
  return(0);
 
3212
}
 
3213
 
 
3214
int map_instanceCache(int (*match)(ccInstance *, void *), void *matchParam, int (*operate)(ccInstance *, void *), void *operateParam) {
 
3215
  int i, ret=0;
 
3216
  
 
3217
  sem_mywait(INSTCACHE);
 
3218
 
 
3219
  for (i=0; i<MAXINSTANCES; i++) {
 
3220
    if (!match(&(instanceCache->instances[i]), matchParam)) {
 
3221
      if (operate(&(instanceCache->instances[i]), operateParam)) {
 
3222
        logprintfl(EUCAWARN, "map_instanceCache(): failed to operate at index %d\n", i);
 
3223
        ret++;
 
3224
      }
 
3225
    }
 
3226
  }
 
3227
  
 
3228
  sem_mypost(INSTCACHE);
 
3229
  return(ret);
 
3230
}
 
3231
 
 
3232
void print_instanceCache(void) {
 
3233
  int i;
 
3234
 
 
3235
  sem_mywait(INSTCACHE);
 
3236
  for (i=0; i<MAXINSTANCES; i++) {
 
3237
    if ( instanceCache->cacheState[i] == INSTVALID ) {
 
3238
      logprintfl(EUCADEBUG,"\tcache: %d/%d %s %s %s %s\n", i, instanceCache->numInsts, instanceCache->instances[i].instanceId, instanceCache->instances[i].ccnet.publicIp, instanceCache->instances[i].ccnet.privateIp, instanceCache->instances[i].state);
 
3239
    }
 
3240
  }
 
3241
  sem_mypost(INSTCACHE);
 
3242
}
 
3243
 
 
3244
void print_ccInstance(char *tag, ccInstance *in) {
 
3245
  char *volbuf, *groupbuf;
 
3246
  int i;
 
3247
 
 
3248
  volbuf = malloc(sizeof(ncVolume)*EUCA_MAX_VOLUMES*2);
 
3249
  bzero(volbuf, sizeof(ncVolume)*EUCA_MAX_VOLUMES*2);
 
3250
 
 
3251
  groupbuf = malloc(64*32*2);
 
3252
  bzero(groupbuf, 64*32*2);
 
3253
  
 
3254
  for (i=0; i<64; i++) {
 
3255
    if (in->groupNames[i][0] != '\0') {
 
3256
      strncat(groupbuf, in->groupNames[i], 32);
 
3257
      strncat(groupbuf, " ", 1);
 
3258
    }
 
3259
  }
 
3260
  
 
3261
  for (i=0; i<EUCA_MAX_VOLUMES; i++) {
 
3262
    if (in->volumes[i].volumeId[0] != '\0') {
 
3263
      strncat(volbuf, in->volumes[i].volumeId, CHAR_BUFFER_SIZE);
 
3264
      strncat(volbuf, ",", 1);
 
3265
      strncat(volbuf, in->volumes[i].remoteDev, CHAR_BUFFER_SIZE);
 
3266
      strncat(volbuf, ",", 1);
 
3267
      strncat(volbuf, in->volumes[i].localDev, CHAR_BUFFER_SIZE);
 
3268
      strncat(volbuf, ",", 1);
 
3269
      strncat(volbuf, in->volumes[i].stateName, CHAR_BUFFER_SIZE);
 
3270
      strncat(volbuf, " ", 1);
 
3271
    }
 
3272
  }
 
3273
  
 
3274
  logprintfl(EUCADEBUG, "print_ccInstance(): %s instanceId=%s reservationId=%s emiId=%s kernelId=%s ramdiskId=%s emiURL=%s kernelURL=%s ramdiskURL=%s state=%s ts=%d ownerId=%s keyName=%s ccnet={privateIp=%s publicIp=%s privateMac=%s vlan=%d networkIndex=%d} ccvm={cores=%d mem=%d disk=%d} ncHostIdx=%d serviceTag=%s userData=%s launchIndex=%s volumesSize=%d volumes={%s} groupNames={%s}\n", tag, in->instanceId, in->reservationId, in->amiId, in->kernelId, in->ramdiskId, in->amiURL, in->kernelURL, in->ramdiskURL, in->state, in->ts, in->ownerId, in->keyName, in->ccnet.privateIp, in->ccnet.publicIp, in->ccnet.privateMac, in->ccnet.vlan, in->ccnet.networkIndex, in->ccvm.cores, in->ccvm.mem, in->ccvm.disk, in->ncHostIdx, in->serviceTag, in->userData, in->launchIndex, in->volumesSize, volbuf, groupbuf);
 
3275
 
 
3276
  free(volbuf);
 
3277
  free(groupbuf);
 
3278
}
 
3279
 
 
3280
void invalidate_instanceCache(void) {
 
3281
  int i;
 
3282
  
 
3283
  sem_mywait(INSTCACHE);
 
3284
  for (i=0; i<MAXINSTANCES; i++) {
 
3285
    // if instance is in teardown, free up network information
 
3286
    if ( !strcmp(instanceCache->instances[i].state, "Teardown") ) {
 
3287
      free_instanceNetwork(instanceCache->instances[i].ccnet.privateMac, instanceCache->instances[i].ccnet.vlan, 0, 0);
 
3288
    }
 
3289
    if ( (instanceCache->cacheState[i] == INSTVALID) && ((time(NULL) - instanceCache->lastseen[i]) > config->instanceTimeout)) {
 
3290
      logprintfl(EUCADEBUG, "invalidate_instanceCache(): invalidating instance '%s' (last seen %d seconds ago)\n", instanceCache->instances[i].instanceId, (time(NULL) - instanceCache->lastseen[i]));
 
3291
      bzero(&(instanceCache->instances[i]), sizeof(ccInstance));
 
3292
      instanceCache->lastseen[i] = 0;
 
3293
      instanceCache->cacheState[i] = INSTINVALID;
 
3294
      instanceCache->numInsts--;
 
3295
    }
 
3296
  }
 
3297
  sem_mypost(INSTCACHE);
 
3298
}
 
3299
 
 
3300
int refresh_instanceCache(char *instanceId, ccInstance *in){
 
3301
  int i, done, rc;
 
3302
  
 
3303
  if (!instanceId || !in) {
 
3304
    return(1);
 
3305
  }
 
3306
  
 
3307
  sem_mywait(INSTCACHE);
 
3308
  done=0;
 
3309
  for (i=0; i<MAXINSTANCES && !done; i++) {
 
3310
    if (!strcmp(instanceCache->instances[i].instanceId, instanceId)) {
 
3311
      // in cache
 
3312
      memcpy(&(instanceCache->instances[i]), in, sizeof(ccInstance));
 
3313
      instanceCache->lastseen[i] = time(NULL);
 
3314
      sem_mypost(INSTCACHE);
 
3315
      return(0);
 
3316
    }
 
3317
  }
 
3318
  sem_mypost(INSTCACHE);
 
3319
 
 
3320
  add_instanceCache(instanceId, in);
 
3321
 
 
3322
  return(0);
 
3323
}
 
3324
 
 
3325
int add_instanceCache(char *instanceId, ccInstance *in){
 
3326
  int i, done, firstNull=0;
 
3327
 
 
3328
  if (!instanceId || !in) {
 
3329
    return(1);
 
3330
  }
 
3331
  
 
3332
  sem_mywait(INSTCACHE);
 
3333
  done=0;
 
3334
  for (i=0; i<MAXINSTANCES && !done; i++) {
 
3335
    if ( (instanceCache->cacheState[i] == INSTVALID ) && (!strcmp(instanceCache->instances[i].instanceId, instanceId))) {
 
3336
      // already in cache
 
3337
      logprintfl(EUCADEBUG, "add_instanceCache(): '%s/%s/%s' already in cache\n", instanceId, in->ccnet.publicIp, in->ccnet.privateIp);
 
3338
      instanceCache->lastseen[i] = time(NULL);
 
3339
      sem_mypost(INSTCACHE);
 
3340
      return(0);
 
3341
    } else if ( instanceCache->cacheState[i] == INSTINVALID ) {
 
3342
      firstNull = i;
 
3343
      done++;
 
3344
    }
 
3345
  }
 
3346
  logprintfl(EUCADEBUG, "add_instanceCache(): adding '%s/%s/%s/%d' to cache\n", instanceId, in->ccnet.publicIp, in->ccnet.privateIp, in->volumesSize);
 
3347
  allocate_ccInstance(&(instanceCache->instances[firstNull]), in->instanceId, in->amiId, in->kernelId, in->ramdiskId, in->amiURL, in->kernelURL, in->ramdiskURL, in->ownerId, in->state, in->ts, in->reservationId, &(in->ccnet), &(in->ccvm), in->ncHostIdx, in->keyName, in->serviceTag, in->userData, in->launchIndex, in->groupNames, in->volumes, in->volumesSize);
 
3348
  instanceCache->numInsts++;
 
3349
  instanceCache->lastseen[firstNull] = time(NULL);
 
3350
  instanceCache->cacheState[firstNull] = INSTVALID;
 
3351
 
 
3352
  sem_mypost(INSTCACHE);
 
3353
  return(0);
 
3354
}
 
3355
 
 
3356
int del_instanceCacheId(char *instanceId) {
 
3357
  int i;
 
3358
 
 
3359
  sem_mywait(INSTCACHE);
 
3360
  for (i=0; i<MAXINSTANCES; i++) {
 
3361
    if ( (instanceCache->cacheState[i] == INSTVALID) && (!strcmp(instanceCache->instances[i].instanceId, instanceId))) {
 
3362
      // del from cache
 
3363
      bzero(&(instanceCache->instances[i]), sizeof(ccInstance));
 
3364
      instanceCache->lastseen[i] = 0;
 
3365
      instanceCache->cacheState[i] = INSTINVALID;
 
3366
      instanceCache->numInsts--;
 
3367
      sem_mypost(INSTCACHE);
 
3368
      return(0);
 
3369
    }
 
3370
  }
 
3371
  sem_mypost(INSTCACHE);
 
3372
  return(0);
 
3373
}
 
3374
 
 
3375
int find_instanceCacheId(char *instanceId, ccInstance **out) {
 
3376
  int i, done;
 
3377
  
 
3378
  if (!instanceId || !out) {
 
3379
    return(1);
 
3380
  }
 
3381
  
 
3382
  sem_mywait(INSTCACHE);
 
3383
  *out = NULL;
 
3384
  done=0;
 
3385
  for (i=0; i<MAXINSTANCES && !done; i++) {
 
3386
    if (!strcmp(instanceCache->instances[i].instanceId, instanceId)) {
 
3387
      // found it
 
3388
      *out = malloc(sizeof(ccInstance));
 
3389
      if (!*out) {
 
3390
        logprintfl(EUCAFATAL, "find_instanceCacheId(): out of memory!\n");
 
3391
        unlock_exit(1);
 
3392
      }
 
3393
 
 
3394
      allocate_ccInstance(*out, instanceCache->instances[i].instanceId,instanceCache->instances[i].amiId, instanceCache->instances[i].kernelId, instanceCache->instances[i].ramdiskId, instanceCache->instances[i].amiURL, instanceCache->instances[i].kernelURL, instanceCache->instances[i].ramdiskURL, instanceCache->instances[i].ownerId, instanceCache->instances[i].state,instanceCache->instances[i].ts, instanceCache->instances[i].reservationId, &(instanceCache->instances[i].ccnet), &(instanceCache->instances[i].ccvm), instanceCache->instances[i].ncHostIdx, instanceCache->instances[i].keyName, instanceCache->instances[i].serviceTag, instanceCache->instances[i].userData, instanceCache->instances[i].launchIndex, instanceCache->instances[i].groupNames, instanceCache->instances[i].volumes, instanceCache->instances[i].volumesSize);
 
3395
      logprintfl(EUCADEBUG, "find_instanceCache(): found instance in cache '%s/%s/%s'\n", instanceCache->instances[i].instanceId, instanceCache->instances[i].ccnet.publicIp, instanceCache->instances[i].ccnet.privateIp);
 
3396
      done++;
 
3397
    }
 
3398
  }
 
3399
  sem_mypost(INSTCACHE);
 
3400
  if (done) {
 
3401
    return(0);
 
3402
  }
 
3403
  return(1);
 
3404
}
 
3405
 
 
3406
int find_instanceCacheIP(char *ip, ccInstance **out) {
 
3407
  int i, done;
 
3408
  
 
3409
  if (!ip || !out) {
 
3410
    return(1);
 
3411
  }
 
3412
  
 
3413
  sem_mywait(INSTCACHE);
 
3414
  *out = NULL;
 
3415
  done=0;
 
3416
  for (i=0; i<MAXINSTANCES && !done; i++) {
 
3417
    if ((instanceCache->instances[i].ccnet.publicIp[0] != '\0' || instanceCache->instances[i].ccnet.privateIp[0] != '\0')) {
 
3418
      if (!strcmp(instanceCache->instances[i].ccnet.publicIp, ip) || !strcmp(instanceCache->instances[i].ccnet.privateIp, ip)) {
 
3419
        // found it
 
3420
        *out = malloc(sizeof(ccInstance));
 
3421
        if (!*out) {
 
3422
          logprintfl(EUCAFATAL, "find_instanceCacheIP(): out of memory!\n");
 
3423
          unlock_exit(1);
 
3424
        }
 
3425
        
 
3426
        allocate_ccInstance(*out, instanceCache->instances[i].instanceId,instanceCache->instances[i].amiId, instanceCache->instances[i].kernelId, instanceCache->instances[i].ramdiskId, instanceCache->instances[i].amiURL, instanceCache->instances[i].kernelURL, instanceCache->instances[i].ramdiskURL, instanceCache->instances[i].ownerId, instanceCache->instances[i].state,instanceCache->instances[i].ts, instanceCache->instances[i].reservationId, &(instanceCache->instances[i].ccnet), &(instanceCache->instances[i].ccvm), instanceCache->instances[i].ncHostIdx, instanceCache->instances[i].keyName, instanceCache->instances[i].serviceTag, instanceCache->instances[i].userData, instanceCache->instances[i].launchIndex, instanceCache->instances[i].groupNames, instanceCache->instances[i].volumes, instanceCache->instances[i].volumesSize);
 
3427
        done++;
 
3428
      }
 
3429
    }
 
3430
  }
 
3431
 
 
3432
  sem_mypost(INSTCACHE);
 
3433
  if (done) {
 
3434
    return(0);
 
3435
  }
 
3436
  return(1);
 
3437
}
 
3438
 
 
3439
 
 
3440
void print_resourceCache(void) {
 
3441
  int i;
 
3442
 
 
3443
  sem_mywait(RESCACHE);
 
3444
  for (i=0; i<MAXNODES; i++) {
 
3445
    if (resourceCache->cacheState[i] == RESVALID) {
 
3446
      logprintfl(EUCADEBUG,"\tcache: %s %s %s %s/%s state=%d\n", resourceCache->resources[i].hostname, resourceCache->resources[i].ncURL, resourceCache->resources[i].ncService, resourceCache->resources[i].mac, resourceCache->resources[i].ip, resourceCache->resources[i].state);
 
3447
    }
 
3448
  }
 
3449
  sem_mypost(RESCACHE);
 
3450
}
 
3451
 
 
3452
void invalidate_resourceCache(void) {
 
3453
  int i;
 
3454
  
 
3455
  sem_mywait(RESCACHE);
 
3456
 
 
3457
  bzero(resourceCache->cacheState, sizeof(int)*MAXNODES);
 
3458
  resourceCache->numResources = 0;
 
3459
  resourceCache->resourceCacheUpdate = 0;
 
3460
 
 
3461
  sem_mypost(RESCACHE);
 
3462
  
 
3463
}
 
3464
 
 
3465
int refresh_resourceCache(char *host, ccResource *in){
 
3466
  int i, done, rc;
 
3467
 
 
3468
  if (!host || !in) {
 
3469
    return(1);
 
3470
  }
 
3471
  
 
3472
  sem_mywait(RESCACHE);
 
3473
  done=0;
 
3474
  for (i=0; i<MAXNODES && !done; i++) {
 
3475
    if (resourceCache->cacheState[i] == RESVALID) {
 
3476
      if (!strcmp(resourceCache->resources[i].hostname, host)) {
 
3477
        // in cache
 
3478
        memcpy(&(resourceCache->resources[i]), in, sizeof(ccResource));
 
3479
        sem_mypost(RESCACHE);
 
3480
        return(0);
 
3481
      }
 
3482
    }
 
3483
  }
 
3484
  sem_mypost(RESCACHE);
 
3485
 
 
3486
  add_resourceCache(host, in);
 
3487
 
 
3488
  return(0);
 
3489
}
 
3490
 
 
3491
int add_resourceCache(char *host, ccResource *in){
 
3492
  int i, done, firstNull=0;
 
3493
 
 
3494
  if (!host || !in) {
 
3495
    return(1);
 
3496
  }
 
3497
  
 
3498
  sem_mywait(RESCACHE);
 
3499
  done=0;
 
3500
  for (i=0; i<MAXNODES && !done; i++) {
 
3501
    if (resourceCache->cacheState[i] == RESVALID) {
 
3502
      if (!strcmp(resourceCache->resources[i].hostname, host)) {
 
3503
        // already in cache
 
3504
        sem_mypost(RESCACHE);
 
3505
        return(0);
 
3506
      }
 
3507
    } else {
 
3508
      firstNull = i;
 
3509
      done++;
 
3510
    }
 
3511
  }
 
3512
  resourceCache->cacheState[firstNull] = RESVALID;
 
3513
  allocate_ccResource(&(resourceCache->resources[firstNull]), in->ncURL, in->ncService, in->ncPort, in->hostname, in->mac, in->ip, in->maxMemory, in->availMemory, in->maxDisk, in->availDisk, in->maxCores, in->availCores, in->state, in->lastState, in->stateChange, in->idleStart);
 
3514
 
 
3515
  resourceCache->numResources++;
 
3516
  sem_mypost(RESCACHE);
 
3517
  return(0);
 
3518
}
 
3519
 
 
3520
int del_resourceCacheId(char *host) {
 
3521
  int i;
 
3522
 
 
3523
  sem_mywait(RESCACHE);
 
3524
  for (i=0; i<MAXNODES; i++) {
 
3525
    if (resourceCache->cacheState[i] == RESVALID) {
 
3526
      if (!strcmp(resourceCache->resources[i].hostname, host)) {
 
3527
        // del from cache
 
3528
        bzero(&(resourceCache->resources[i]), sizeof(ccResource));
 
3529
        resourceCache->cacheState[i] = RESINVALID;
 
3530
        resourceCache->numResources--;
 
3531
        sem_mypost(RESCACHE);
 
3532
        return(0);
 
3533
      }
 
3534
    }
 
3535
  }
 
3536
  sem_mypost(RESCACHE);
 
3537
  return(0);
 
3538
}
 
3539
 
 
3540
int find_resourceCacheId(char *host, ccResource **out) {
 
3541
  int i, done;
 
3542
  
 
3543
  if (!host || !out) {
 
3544
    return(1);
 
3545
  }
 
3546
  
 
3547
  sem_mywait(RESCACHE);
 
3548
  *out = NULL;
 
3549
  done=0;
 
3550
  for (i=0; i<MAXNODES && !done; i++) {
 
3551
    if (resourceCache->cacheState[i] == RESVALID) {
 
3552
      if (!strcmp(resourceCache->resources[i].hostname, host)) {
 
3553
        // found it
 
3554
        *out = malloc(sizeof(ccResource));
 
3555
        if (!*out) {
 
3556
          logprintfl(EUCAFATAL, "find_resourceCacheId(): out of memory!\n");
 
3557
          unlock_exit(1);
 
3558
        }
 
3559
        allocate_ccResource(*out, resourceCache->resources[i].ncURL, resourceCache->resources[i].ncService, resourceCache->resources[i].ncPort, resourceCache->resources[i].hostname, resourceCache->resources[i].mac, resourceCache->resources[i].ip, resourceCache->resources[i].maxMemory, resourceCache->resources[i].availMemory, resourceCache->resources[i].maxDisk, resourceCache->resources[i].availDisk, resourceCache->resources[i].maxCores, resourceCache->resources[i].availCores, resourceCache->resources[i].state, resourceCache->resources[i].lastState, resourceCache->resources[i].stateChange, resourceCache->resources[i].idleStart);
 
3560
        done++;
 
3561
      }
 
3562
    }
 
3563
  }
 
3564
 
 
3565
  sem_mypost(RESCACHE);
 
3566
  if (done) {
 
3567
    return(0);
 
3568
  }
 
3569
  return(1);
 
3570
}
 
3571
 
 
3572
void unlock_exit(int code) {
 
3573
  int i;
 
3574
  
 
3575
  logprintfl(EUCADEBUG, "unlock_exit(): params: code=%d\n", code);
 
3576
  
 
3577
  for (i=0; i<ENDLOCK; i++) {
 
3578
    if (mylocks[i]) {
 
3579
      logprintfl(EUCAWARN, "unlock_exit(): unlocking index '%d'\n", i);
 
3580
      sem_post(locks[i]);
 
3581
    }
 
3582
  }
 
3583
  exit(code);
 
3584
}
 
3585
 
 
3586
int sem_mywait(int lockno) {
 
3587
  int rc;
 
3588
  rc = sem_wait(locks[lockno]);
 
3589
  mylocks[lockno] = 1;
 
3590
  return(rc);
 
3591
}
 
3592
int sem_mypost(int lockno) {
 
3593
  mylocks[lockno] = 0;
 
3594
  return(sem_post(locks[lockno]));
 
3595
}
 
3596
 
 
3597