2
Copyright (c) 2009 Eucalyptus Systems, Inc.
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.
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
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/>.
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.
20
This file may incorporate work covered under the following copyright and
23
Software License Agreement (BSD License)
25
Copyright (c) 2008, Regents of the University of California
28
Redistribution and use of this software in source and binary forms, with
29
or without modification, are permitted provided that the following
32
Redistributions of source code must retain the above copyright notice,
33
this list of conditions and the following disclaimer.
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.
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.
62
#include <sys/types.h>
66
#include <semaphore.h>
68
#include <sys/socket.h>
69
#include <netinet/in.h>
70
#include <arpa/inet.h>
73
#include "axis2_skel_EucalyptusCC.h"
75
#include <server-marshal.h>
82
#include <euca_axis.h>
84
#include "client-marshal.h"
86
#include <euca_auth.h>
88
#define SUPERUSER "eucalyptus"
96
// to be stored in shared memory
97
ccConfig *config=NULL;
99
ccInstanceCache *instanceCache=NULL;
101
ccResourceCache *resourceCache=NULL;
103
vnetConfig *vnetconfig=NULL;
105
sem_t *locks[ENDLOCK] = {NULL, NULL, NULL, NULL, NULL, NULL};
106
int mylocks[ENDLOCK] = {0,0,0,0,0,0};
108
int ncClientCall(ncMetadata *meta, int timeout, int ncLock, char *ncURL, char *ncOp, ...) {
110
int pid, rc=0, ret=0, status=0, opFail=0, len, rbytes, i;
113
logprintfl(EUCADEBUG, "ncClientCall(%s): called ncURL=%s timeout=%d\n", ncOp, ncURL, timeout);
117
logprintfl(EUCAERROR, "ncClientCall(%s): cannot create pipe\n", ncOp);
131
ncs = ncStubCreate(ncURL, NULL, NULL);
132
if (config->use_wssec) {
133
rc = InitWSSEC(ncs->env, ncs->stub, config->policyFile);
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 **);
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);
151
rc = write(filedes[1], &len, sizeof(int));
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 *);
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);
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 *);
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 *);
181
rc = ncTerminateInstanceStub(ncs, meta, instId, shutdownState, previousState);
185
rc = write(filedes[1], &len, sizeof(int));
186
rc = write(filedes[1], shutdownState, sizeof(int));
187
rc = write(filedes[1], previousState, sizeof(int));
191
rc = write(filedes[1], &len, sizeof(int));
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 **);
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);
211
rc = write(filedes[1], &len, sizeof(int));
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 **);
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));
242
rc = write(filedes[1], &len, sizeof(int));
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 *);
252
rc = ncDescribeInstancesStub(ncs, meta, instIds, instIdsLen, ncOutInsts, ncOutInstsLen);
253
if (timeout && ncOutInsts && ncOutInstsLen) {
255
len = *ncOutInstsLen;
256
rc = write(filedes[1], &len, sizeof(int));
257
for (i=0; i<len; i++) {
259
inst = (*ncOutInsts)[i];
260
rc = write(filedes[1], inst, sizeof(ncInstance));
265
rc = write(filedes[1], &len, sizeof(int));
269
} else if (!strcmp(ncOp, "ncDescribeResource")) {
270
char *resourceType = va_arg(al, char *);
271
ncResource **outRes=va_arg(al, ncResource **);
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));
282
rc = write(filedes[1], &len, sizeof(int));
287
logprintfl(EUCAWARN, "\tncClientCall(%s): ppid=%d operation '%s' not found\n", ncOp, getppid(), ncOp);
290
logprintfl(EUCADEBUG, "\tncClientCall(%s): ppid=%d done calling '%s' with exit code '%d'\n", ncOp, getppid(), ncOp, rc);
299
// returns for each client call
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;
308
if (timeout && outConsoleOutput) {
309
rbytes = timeread(filedes[0], &len, sizeof(int), timeout);
314
*outConsoleOutput = malloc(sizeof(char) * len);
315
if (!*outConsoleOutput) {
316
logprintfl(EUCAFATAL, "ncClientCall(%s): out of memory!\n", ncOp);
319
rbytes = timeread(filedes[0], *outConsoleOutput, len, timeout);
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;
333
if (timeout && shutdownState && previousState) {
334
rbytes = timeread(filedes[0], &len, sizeof(int), timeout);
339
rbytes = timeread(filedes[0], shutdownState, sizeof(int), timeout);
344
rbytes = timeread(filedes[0], previousState, sizeof(int), timeout);
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 **);
360
if (timeout && outStatus) {
362
rbytes = timeread(filedes[0], &len, sizeof(int), timeout);
367
*outStatus = malloc(sizeof(char) * len);
369
logprintfl(EUCAFATAL, "ncClientCall(%s): out of memory!\n", ncOp);
372
rbytes = timeread(filedes[0], *outStatus, len, timeout);
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 **);
399
if (timeout && outInst) {
400
rbytes = timeread(filedes[0], &len, sizeof(int), timeout);
405
*outInst = malloc(sizeof(ncInstance));
407
logprintfl(EUCAFATAL, "ncClientCall(%s): out of memory!\n", ncOp);
410
rbytes = timeread(filedes[0], *outInst, sizeof(ncInstance), timeout);
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) {
426
if (timeout && ncOutInsts && ncOutInstsLen) {
427
rbytes = timeread(filedes[0], &len, sizeof(int), timeout);
432
*ncOutInsts = malloc(sizeof(ncInstance *) * len);
434
logprintfl(EUCAFATAL, "ncClientCall(%s): out of memory!\n", ncOp);
437
*ncOutInstsLen = len;
438
for (i=0; i<len; i++) {
440
inst = malloc(sizeof(ncInstance));
442
logprintfl(EUCAFATAL, "ncClientCall(%s): out of memory!\n", ncOp);
445
rbytes = timeread(filedes[0], inst, sizeof(ncInstance), timeout);
446
(*ncOutInsts)[i] = inst;
450
} else if (!strcmp(ncOp, "ncDescribeResource")) {
451
char *resourceType = va_arg(al, char *);
452
ncResource **outRes=va_arg(al, ncResource **);
456
if (timeout && outRes) {
457
rbytes = timeread(filedes[0], &len, sizeof(int), timeout);
462
*outRes = malloc(sizeof(ncResource));
464
logprintfl(EUCAFATAL, "ncClientCall(%s): out of memory!\n", ncOp);
467
rbytes = timeread(filedes[0], *outRes, sizeof(ncResource), timeout);
475
// nothing to do in default case (succ/fail encoded in exit code)
480
rc = timewait(pid, &status, timeout);
481
rc = WEXITSTATUS(status);
487
logprintfl(EUCADEBUG, "ncClientCall(%s): done clientrc=%d opFail=%d\n", ncOp, rc, opFail);
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;
507
numLeft = numCalls - idx;
508
if ( numLeft <= 0 ) {
512
op_timer = op_max - (time(NULL) - op_start);
513
op_pernode = op_timer / numLeft;
515
return(maxint(minint(op_pernode, OP_TIMEOUT_PERNODE), OP_TIMEOUT_MIN));
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;
523
ccResourceCache resourceCacheLocal;
527
op_start = time(NULL);
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");
541
sem_mywait(RESCACHE);
542
memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache));
543
sem_mypost(RESCACHE);
545
rc = find_instanceCacheId(instanceId, &myInstance);
547
// found the instance in the cache
549
start = myInstance->ncHostIdx;
555
stop = resourceCacheLocal.numResources;
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);
570
logprintfl(EUCADEBUG,"AttachVolume(): done.\n");
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;
582
ccResourceCache resourceCacheLocal;
585
op_start = time(NULL);
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");
598
sem_mywait(RESCACHE);
599
memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache));
600
sem_mypost(RESCACHE);
602
rc = find_instanceCacheId(instanceId, &myInstance);
604
// found the instance in the cache
606
start = myInstance->ncHostIdx;
612
stop = resourceCacheLocal.numResources;
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);
626
logprintfl(EUCADEBUG,"DetachVolume(): done.\n");
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) {
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);
644
if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) {
648
if (destUserName == NULL) {
649
destUserName = meta->userId;
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);
660
logprintfl(EUCAERROR,"ERROR: vnetTableRule() returned error\n");
664
for (i=0; i<netLen; i++) {
666
rc = vnetTableRule(vnetconfig, type, destUserName, destName, NULL, sourceNets[i], NULL, protocol, minPort, maxPort);
669
logprintfl(EUCAERROR,"ERROR: vnetTableRule() returned error\n");
676
logprintfl(EUCADEBUG,"ConfigureNetwork(): done\n");
686
int doFlushNetwork(ncMetadata *ccMeta, char *destName) {
689
if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) {
694
rc = vnetFlushTable(vnetconfig, ccMeta->userId, destName);
699
int doAssignAddress(ncMetadata *ccMeta, char *src, char *dst) {
700
int rc, allocated, addrdevno, ret;
702
ccInstance *myInstance=NULL;
708
logprintfl(EUCAINFO,"AssignAddress(): called\n");
709
logprintfl(EUCADEBUG,"AssignAddress(): params: src=%s, dst=%s\n", SP(src), SP(dst));
711
if (!src || !dst || !strcmp(src, "0.0.0.0") || !strcmp(dst, "0.0.0.0")) {
712
logprintfl(EUCADEBUG, "AssignAddress(): bad input params\n");
718
if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) {
723
rc = vnetGetPublicIP(vnetconfig, src, NULL, &allocated, &addrdevno);
725
logprintfl(EUCAERROR,"AssignAddress(): failed to retrieve publicip record %s\n", src);
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);
733
if (rc && (rc != 2)) {
734
logprintfl(EUCAERROR,"AssignAddress(): cmd '%s' failed\n", cmd);
737
rc = vnetAssignAddress(vnetconfig, src, dst);
739
logprintfl(EUCAERROR,"AssignAddress(): vnetAssignAddress() failed\n");
742
rc = vnetAllocatePublicIP(vnetconfig, src, dst);
744
logprintfl(EUCAERROR,"AssignAddress(): vnetAllocatePublicIP() failed\n");
750
logprintfl(EUCAWARN,"AssignAddress(): ip %s is already assigned, ignoring\n", src);
758
// everything worked, update instance cache
760
rc = map_instanceCache(privIpCmp, dst, pubIpSet, src);
762
logprintfl(EUCAERROR, "AssignAddress(): map_instanceCache() failed to assign %s->%s\n", dst, src);
766
logprintfl(EUCADEBUG,"AssignAddress(): done\n");
773
int doDescribePublicAddresses(ncMetadata *ccMeta, publicip **outAddresses, int *outAddressesLen) {
781
logprintfl(EUCAINFO, "DescribePublicAddresses(): called\n");
782
logprintfl(EUCADEBUG, "DescribePublicAddresses(): params: userId=%s\n", SP(ccMeta ? ccMeta->userId : "UNSET"));
785
if (!strcmp(vnetconfig->mode, "MANAGED") || !strcmp(vnetconfig->mode, "MANAGED-NOVLAN")) {
786
*outAddresses = vnetconfig->publicips;
787
*outAddressesLen = NUMBER_OF_PUBLIC_IPS;
789
*outAddresses = NULL;
790
*outAddressesLen = 0;
794
logprintfl(EUCADEBUG, "DescribePublicAddresses(): done\n");
801
int doUnassignAddress(ncMetadata *ccMeta, char *src, char *dst) {
802
int rc, allocated, addrdevno, ret;
804
ccInstance *myInstance=NULL;
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));
813
if (!src || !dst || !strcmp(src, "0.0.0.0") || !strcmp(dst, "0.0.0.0")) {
814
logprintfl(EUCADEBUG, "UnassignAddress(): bad input params\n");
818
if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) {
824
rc = vnetGetPublicIP(vnetconfig, src, NULL, &allocated, &addrdevno);
826
logprintfl(EUCAERROR,"UnassignAddress(): failed to find publicip to unassign (%s)\n", src);
829
if (allocated && dst) {
830
rc = vnetUnassignAddress(vnetconfig, src, dst);
832
logprintfl(EUCAWARN,"vnetUnassignAddress() failed %d: %s/%s\n", rc, src, dst);
835
rc = vnetDeallocatePublicIP(vnetconfig, src, dst);
837
logprintfl(EUCAWARN,"vnetDeallocatePublicIP() failed %d: %s\n", rc, src);
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);
846
logprintfl(EUCAWARN,"UnassignAddress(): cmd failed '%s'\n", cmd);
853
// refresh instance cache
854
rc = map_instanceCache(pubIpCmp, src, pubIpSet, "0.0.0.0");
856
logprintfl(EUCAERROR, "UnassignAddress(): map_instanceCache() failed to assign %s->%s\n", dst, src);
860
logprintfl(EUCADEBUG,"UnassignAddress(): done\n");
867
int doStopNetwork(ncMetadata *ccMeta, char *netName, int vlan) {
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");
881
if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) {
887
rc = vnetStopNetwork(vnetconfig, vlan, ccMeta->userId, netName);
893
logprintfl(EUCADEBUG,"StopNetwork(): done\n");
900
int doDescribeNetworks(ncMetadata *ccMeta, char *nameserver, char **ccs, int ccsLen, vnetConfig *outvnetConfig) {
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);
913
vnetconfig->euca_ns = dot2hex(nameserver);
915
if (!strcmp(vnetconfig->mode, "MANAGED") || !strcmp(vnetconfig->mode, "MANAGED-NOVLAN")) {
916
rc = vnetSetCCS(vnetconfig, ccs, ccsLen);
917
rc = vnetSetupTunnels(vnetconfig);
919
memcpy(outvnetConfig, vnetconfig, sizeof(vnetConfig));
922
logprintfl(EUCADEBUG, "DescribeNetworks(): done\n");
929
int doStartNetwork(ncMetadata *ccMeta, char *netName, int vlan, char *nameserver, char **ccs, int ccsLen) {
934
op_start = time(NULL);
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);
944
if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) {
949
vnetconfig->euca_ns = dot2hex(nameserver);
952
rc = vnetSetCCS(vnetconfig, ccs, ccsLen);
953
rc = vnetSetupTunnels(vnetconfig);
956
rc = vnetStartNetwork(vnetconfig, vlan, ccMeta->userId, netName, &brname);
957
if (brname) free(brname);
962
logprintfl(EUCAERROR,"StartNetwork(): vnetStartNetwork() failed (%d)\n", rc);
970
logprintfl(EUCADEBUG,"StartNetwork(): done\n");
977
int doDescribeResources(ncMetadata *ccMeta, virtualMachine **ccvms, int vmLen, int **outTypesMax, int **outTypesAvail, int *outTypesLen, char ***outServiceTags, int *outServiceTagsLen) {
979
int rc, diskpool, mempool, corepool;
983
ccResourceCache resourceCacheLocal;
986
logprintfl(EUCAINFO,"DescribeResources(): called\n");
987
logprintfl(EUCADEBUG,"DescribeResources(): params: userId=%s, vmLen=%d\n", SP(ccMeta ? ccMeta->userId : "UNSET"), vmLen);
989
op_start = time(NULL);
996
if (outTypesMax == NULL || outTypesAvail == NULL || outTypesLen == NULL || outServiceTags == NULL || outServiceTagsLen == NULL) {
1001
*outTypesMax = NULL;
1002
*outTypesAvail = NULL;
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");
1010
bzero(*outTypesMax, sizeof(int) * vmLen);
1011
bzero(*outTypesAvail, sizeof(int) * vmLen);
1013
*outTypesLen = vmLen;
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);
1021
*outServiceTags = NULL;
1022
*outServiceTagsLen = 0;
1027
sem_mywait(RESCACHE);
1028
memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache));
1029
sem_mypost(RESCACHE);
1031
*outServiceTags = malloc(sizeof(char *) * resourceCacheLocal.numResources);
1032
if (*outServiceTags == NULL) {
1033
logprintfl(EUCAFATAL,"DescribeResources(): out of memory!\n");
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");
1047
for (i=0; i<resourceCacheLocal.numResources; i++) {
1048
res = &(resourceCacheLocal.resources[i]);
1050
for (j=0; j<vmLen; j++) {
1051
mempool = res->availMemory;
1052
diskpool = res->availDisk;
1053
corepool = res->availCores;
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;
1065
mempool = res->maxMemory;
1066
diskpool = res->maxDisk;
1067
corepool = res->maxCores;
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;
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]);
1085
logprintfl(EUCADEBUG,"DescribeResources(): done\n");
1092
int changeState(ccResource *in, int newstate) {
1093
if (in == NULL) return(1);
1094
if (in->state == newstate) return(0);
1096
in->lastState = in->state;
1097
in->state = newstate;
1098
in->stateChange = time(NULL);
1104
int refresh_resources(ncMetadata *ccMeta, int timeout, int dolock) {
1105
int i, rc, nctimeout;
1110
ncResource *ncResDst=NULL;
1111
ccResourceCache resourceCacheLocal;
1113
if (timeout <= 0) timeout = 1;
1115
op_start = time(NULL);
1116
logprintfl(EUCAINFO,"refresh_resources(): called\n");
1118
rc = update_config();
1120
logprintfl(EUCAWARN, "refresh_resources(): bad return from update_config(), check your config file\n");
1123
// critical NC call section
1124
sem_mywait(RESCACHE);
1125
memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache));
1126
sem_mypost(RESCACHE);
1128
for (i=0; i<resourceCacheLocal.numResources; i++) {
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);
1134
powerUp(&(resourceCacheLocal.resources[i]));
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));
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);
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);
1159
logprintfl(EUCADEBUG, "refresh_resources(): resource asleep/running instances (%d), skipping resource update\n", resourceCacheLocal.resources[i].running);
1162
// try to discover the mac address of the resource
1163
if (resourceCacheLocal.resources[i].mac[0] == '\0' && resourceCacheLocal.resources[i].ip[0] != '\0') {
1165
rc = ip2mac(vnetconfig, resourceCacheLocal.resources[i].ip, &mac);
1167
strncpy(resourceCacheLocal.resources[i].mac, mac, 24);
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);
1172
if (ncResDst) free(ncResDst);
1175
sem_mywait(RESCACHE);
1176
memcpy(resourceCache, &resourceCacheLocal, sizeof(ccResourceCache));
1177
sem_mypost(RESCACHE);
1179
logprintfl(EUCADEBUG,"refresh_resources(): done\n");
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;
1188
ncInstance **ncOutInsts=NULL;
1191
ccResourceCache resourceCacheLocal;
1193
op_start = time(NULL);
1195
logprintfl(EUCAINFO,"refresh_instances(): called\n");
1197
// critical NC call section
1198
sem_mywait(RESCACHE);
1199
memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache));
1200
sem_mypost(RESCACHE);
1202
invalidate_instanceCache();
1204
for (i=0; i<resourceCacheLocal.numResources; i++) {
1205
if (resourceCacheLocal.resources[i].state == RESUP) {
1208
nctimeout = ncGetTimeout(op_start, timeout, resourceCacheLocal.numResources, i);
1209
rc = ncClientCall(ccMeta, nctimeout, NCCALL, resourceCacheLocal.resources[i].ncURL, "ncDescribeInstances", NULL, 0, &ncOutInsts, &ncOutInstsLen);
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) {
1220
if (powerDown(ccMeta, &(resourceCacheLocal.resources[i]))) {
1221
logprintfl(EUCAWARN, "refresh_instances(): powerDown for %s failed\n", resourceCacheLocal.resources[i].hostname);
1225
resourceCacheLocal.resources[i].idleStart = 0;
1228
// populate instanceCache
1229
for (j=0; j<ncOutInstsLen; j++) {
1234
logprintfl(EUCADEBUG,"refresh_instances(): describing instance %s, %s, %d\n", ncOutInsts[j]->instanceId, ncOutInsts[j]->stateName, j);
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));
1242
logprintfl(EUCAFATAL, "refresh_instances(): out of memory!\n");
1245
bzero(myInstance, sizeof(ccInstance));
1248
// update CC instance with instance state from NC
1249
rc = ccInstance_to_ncInstance(myInstance, ncOutInsts[j]);
1251
// instance info that the CC maintains
1252
myInstance->ncHostIdx = i;
1253
strncpy(myInstance->serviceTag, resourceCacheLocal.resources[i].ncURL, 64);
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);
1260
strncpy(myInstance->ccnet.publicIp, ip, 24);
1268
if (!strcmp(myInstance->ccnet.privateIp, "0.0.0.0")) {
1269
rc = mac2ip(vnetconfig, myInstance->ccnet.privateMac, &ip);
1271
strncpy(myInstance->ccnet.privateIp, ip, 24);
1278
refresh_instanceCache(myInstance->instanceId, myInstance);
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);
1283
if (myInstance) free(myInstance);
1288
for (j=0; j<ncOutInstsLen; j++) {
1289
free_instance(&(ncOutInsts[j]));
1297
sem_mywait(RESCACHE);
1298
memcpy(resourceCache, &resourceCacheLocal, sizeof(ccResourceCache));
1299
sem_mypost(RESCACHE);
1301
logprintfl(EUCADEBUG,"refresh_instances(): done\n");
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;
1311
ncInstance **ncOutInsts=NULL;
1314
logprintfl(EUCAINFO,"DescribeInstances(): called\n");
1315
logprintfl(EUCADEBUG,"DescribeInstances(): params: userId=%s, instIdsLen=%d\n", SP(ccMeta ? ccMeta->userId : "UNSET"), instIdsLen);
1317
op_start = time(NULL);
1327
sem_mywait(INSTCACHE);
1329
if (instanceCache->numInsts) {
1330
*outInsts = malloc(sizeof(ccInstance) * instanceCache->numInsts);
1332
logprintfl(EUCAFATAL, "doDescribeInstances(): out of memory!\n");
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");
1342
memcpy( &((*outInsts)[count]), &(instanceCache->instances[i]), sizeof(ccInstance));
1347
*outInstsLen = instanceCache->numInsts;
1349
sem_mypost(INSTCACHE);
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);
1355
logprintfl(EUCADEBUG,"DescribeInstances(): done\n");
1362
int powerUp(ccResource *res) {
1364
char cmd[MAX_PATH], *bc=NULL;
1365
uint32_t *ips=NULL, *nms=NULL;
1367
if (config->schedPolicy != SCHEDPOWERSAVE) {
1371
rc = getdevinfo(vnetconfig->privInterface, &ips, &nms, &len);
1374
ips = malloc(sizeof(uint32_t));
1376
logprintfl(EUCAFATAL, "powerUp(): out of memory!\n");
1380
nms = malloc(sizeof(uint32_t));
1382
logprintfl(EUCAFATAL, "powerUp(): out of memory!\n");
1386
ips[0] = 0xFFFFFFFF;
1387
nms[0] = 0xFFFFFFFF;
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
1396
bc = hex2dot((0xFFFFFFFF - nms[i]) | (ips[i] & nms[i]));
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);
1409
logprintfl(EUCAINFO, "powerUp(): waking up powered off host %s(%s/%s): %s\n", res->hostname, res->ip, res->mac, cmd);
1413
logprintfl(EUCAERROR, "powerUp(): cmd failed: %d\n", rc);
1416
logprintfl(EUCAERROR, "powerUp(): cmd success: %d\n", rc);
1417
changeState(res, RESWAKING);
1427
int powerDown(ncMetadata *ccMeta, ccResource *node) {
1428
int pid, rc, status, timeout;
1432
if (config->schedPolicy != SCHEDPOWERSAVE) {
1433
node->idleStart = 0;
1437
op_start = time(NULL);
1439
logprintfl(EUCAINFO, "powerDown(): sending powerdown to node: %s, %s\n", node->hostname, node->ncURL);
1441
timeout = ncGetTimeout(op_start, OP_TIMEOUT, 1, 1);
1442
rc = ncClientCall(ccMeta, timeout, NCCALL, node->ncURL, "ncPowerDown");
1445
changeState(node, RESASLEEP);
1450
int ccInstance_to_ncInstance(ccInstance *dst, ncInstance *src) {
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;
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);
1471
for (i=0; i < src->groupNamesSize && i < 64; i++) {
1472
snprintf(dst->groupNames[i], 32, "%s", src->groupNames[i]);
1475
memcpy(dst->volumes, src->volumes, sizeof(ncVolume) * EUCA_MAX_VOLUMES);
1476
dst->volumesSize = src->volumesSize;
1478
memcpy(&(dst->ccvm), &(src->params), sizeof(virtualMachine));
1483
int schedule_instance(virtualMachine *vm, char *targetNode, int *outresid) {
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);
1496
ret = schedule_instance_greedy(vm, outresid);
1502
int schedule_instance_roundrobin(virtualMachine *vm, int *outresid) {
1503
int i, done, start, found, resid=0;
1508
logprintfl(EUCADEBUG, "schedule(): scheduler using ROUNDROBIN policy to find next resource\n");
1509
// find the best 'resource' on which to run the instance
1511
start = config->schedState;
1514
logprintfl(EUCADEBUG, "schedule(): scheduler state starting at resource %d\n", config->schedState);
1516
int mem, disk, cores;
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;
1524
if (mem >= 0 && disk >= 0 && cores >= 0) {
1531
if (i >= resourceCache->numResources) {
1540
// didn't find a resource
1545
config->schedState = i;
1547
logprintfl(EUCADEBUG, "schedule(): scheduler state finishing at resource %d\n", config->schedState);
1552
int schedule_instance_explicit(virtualMachine *vm, char *targetNode, int *outresid) {
1553
int i, rc, done, resid, sleepresid;
1558
logprintfl(EUCADEBUG, "schedule(): scheduler using EXPLICIT policy to run VM on target node '%s'\n", targetNode);
1560
// find the best 'resource' on which to run the instance
1561
resid = sleepresid = -1;
1563
for (i=0; i<resourceCache->numResources && !done; i++) {
1564
int mem, disk, cores;
1566
res = &(resourceCache->resources[i]);
1567
if (!strcmp(res->hostname, targetNode)) {
1569
if (res->state == RESUP) {
1570
mem = res->availMemory - vm->mem;
1571
disk = res->availDisk - vm->disk;
1572
cores = res->availCores - vm->cores;
1574
if (mem >= 0 && disk >= 0 && cores >= 0) {
1577
} else if (res->state == RESASLEEP) {
1578
mem = res->availMemory - vm->mem;
1579
disk = res->availDisk - vm->disk;
1580
cores = res->availCores - vm->cores;
1582
if (mem >= 0 && disk >= 0 && cores >= 0) {
1589
if (resid == -1 && sleepresid == -1) {
1590
// target resource is unavailable
1595
res = &(resourceCache->resources[resid]);
1597
} else if (sleepresid != -1) {
1598
res = &(resourceCache->resources[sleepresid]);
1599
*outresid = sleepresid;
1601
if (res->state == RESASLEEP) {
1608
int schedule_instance_greedy(virtualMachine *vm, int *outresid) {
1609
int i, rc, done, resid, sleepresid;
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");
1620
// find the best 'resource' on which to run the instance
1621
resid = sleepresid = -1;
1623
for (i=0; i<resourceCache->numResources && !done; i++) {
1624
int mem, disk, cores;
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;
1632
if (mem >= 0 && disk >= 0 && cores >= 0) {
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;
1641
if (mem >= 0 && disk >= 0 && cores >= 0) {
1647
if (resid == -1 && sleepresid == -1) {
1648
// didn't find a resource
1653
res = &(resourceCache->resources[resid]);
1655
} else if (sleepresid != -1) {
1656
res = &(resourceCache->resources[sleepresid]);
1657
*outresid = sleepresid;
1659
if (res->state == RESASLEEP) {
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,
1672
ccResource *res=NULL;
1673
char mac[32], privip[32], pubip[32];
1675
ncInstance *outInst=NULL;
1676
virtualMachine ncvm;
1680
op_start = time(NULL);
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));
1692
logprintfl(EUCAERROR,"RunInstances(): invalid ccvm\n");
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);
1700
// check health of the networkIndexList
1701
if ( (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) || networkIndexList == NULL) {
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);
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);
1720
retInsts = malloc(sizeof(ccInstance) * maxCount);
1722
logprintfl(EUCAFATAL, "RunInstances(): out of memory!\n");
1728
// get updated resource information
1731
for (i=0; i<maxCount && !done; i++) {
1732
snprintf(instId, 16, "%s", instIds[i]);
1734
logprintfl(EUCADEBUG,"RunInstances(): running instance %s with emiId %s...\n", instId, amiId);
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);
1749
rc = vnetGenerateNetworkParams(vnetconfig, instId, vlan, -1, mac, pubip, privip);
1752
rc = vnetGenerateNetworkParams(vnetconfig, instId, vlan, networkIndexList[nidx], mac, pubip, privip);
1763
if (thenidx != -1) {
1764
logprintfl(EUCADEBUG,"RunInstances(): assigning MAC/IP: %s/%s/%s/%d\n", mac, pubip, privip, networkIndexList[thenidx]);
1766
logprintfl(EUCADEBUG,"RunInstances(): assigning MAC/IP: %s/%s/%s/%d\n", mac, pubip, privip, thenidx);
1769
if (mac[0] == '\0' || !foundnet) {
1770
logprintfl(EUCAERROR,"RunInstances(): could not find/initialize any free network address, failing doRunInstances()\n");
1772
// "run" the instance
1773
memcpy (&ncvm, ccvm, sizeof(virtualMachine));
1777
ncnet.networkIndex = networkIndexList[thenidx];
1779
ncnet.networkIndex = -1;
1781
snprintf(ncnet.privateMac, 24, "%s", mac);
1782
snprintf(ncnet.privateIp, 24, "%s", privip);
1783
snprintf(ncnet.publicIp, 24, "%s", pubip);
1785
sem_mywait(RESCACHE);
1790
rc = schedule_instance(ccvm, targetNode, &resid);
1793
res = &(resourceCache->resources[resid]);
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);
1800
int pid, status, ret, rbytes;
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);
1811
sem_mywait(RESCACHE);
1812
if (res->running > 0) {
1815
sem_mypost(RESCACHE);
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);
1820
startRun = time(NULL);
1821
while(rc && ((time(NULL) - startRun) < config->wakeThresh)){
1824
// call StartNetwork client
1825
rc = ncClientCall(ccMeta, OP_TIMEOUT_PERNODE, NCCALL, res->ncURL, "ncStartNetwork", NULL, 0, 0, vlan, NULL);
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);
1839
sem_mywait(RESCACHE);
1840
if (res->running > 0) {
1843
sem_mypost(RESCACHE);
1848
logprintfl(EUCADEBUG,"RunInstances(): call complete (pid/rc): %d/%d\n", pid, rc);
1852
logprintfl(EUCAERROR, "RunInstances(): tried to run the VM, but runInstance() failed; marking resource '%s' as down\n", res->ncURL);
1853
res->state = RESDOWN;
1855
// couldn't run this VM, remove networking information from system
1856
free_instanceNetwork(mac, vlan, 1, 1);
1858
res->availMemory -= ccvm->mem;
1859
res->availDisk -= ccvm->disk;
1860
res->availCores -= ccvm->cores;
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);
1864
myInstance = &(retInsts[runCount]);
1865
bzero(myInstance, sizeof(ccInstance));
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);
1871
config->kick_dhcp = 1;
1874
// add the instance to the cache, and continue on
1875
add_instanceCache(myInstance->instanceId, myInstance);
1876
print_ccInstance("RunInstances(): ", myInstance);
1882
sem_mypost(RESCACHE);
1887
*outInstsLen = runCount;
1888
*outInsts = retInsts;
1890
logprintfl(EUCADEBUG,"RunInstances(): done\n");
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;
1904
char *consoleOutput;
1906
ccResourceCache resourceCacheLocal;
1908
i = j = numInsts = 0;
1909
op_start = time(NULL);
1911
consoleOutput = NULL;
1914
*outConsoleOutput = NULL;
1921
logprintfl(EUCAINFO,"GetConsoleOutput(): called\n");
1922
logprintfl(EUCADEBUG,"GetConsoleOutput(): params: userId=%s, instId=%s\n", SP(meta->userId), SP(instId));
1924
sem_mywait(RESCACHE);
1925
memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache));
1926
sem_mypost(RESCACHE);
1928
rc = find_instanceCacheId(instId, &myInstance);
1930
// found the instance in the cache
1931
start = myInstance->ncHostIdx;
1936
stop = resourceCacheLocal.numResources;
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);
1953
logprintfl(EUCADEBUG,"GetConsoleOutput(): done.\n");
1960
int doRebootInstances(ncMetadata *meta, char **instIds, int instIdsLen) {
1961
int i, j, rc, numInsts, start, stop, done, timeout=0, ret=0;
1963
ccInstance *myInstance;
1966
ccResourceCache resourceCacheLocal;
1968
i = j = numInsts = 0;
1971
op_start = time(NULL);
1977
logprintfl(EUCAINFO,"RebootInstances(): called\n");
1978
logprintfl(EUCADEBUG,"RebootInstances(): params: userId=%s, instIdsLen=%d\n", SP(meta->userId), instIdsLen);
1980
sem_mywait(RESCACHE);
1981
memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache));
1982
sem_mypost(RESCACHE);
1984
for (i=0; i<instIdsLen; i++) {
1985
instId = instIds[i];
1986
rc = find_instanceCacheId(instId, &myInstance);
1988
// found the instance in the cache
1989
start = myInstance->ncHostIdx;
1994
stop = resourceCacheLocal.numResources;
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);
2010
logprintfl(EUCADEBUG,"RebootInstances(): done.\n");
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;
2020
ccInstance *myInstance=NULL;
2023
ccResourceCache resourceCacheLocal;
2028
op_start = time(NULL);
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"));
2037
sem_mywait(RESCACHE);
2038
memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache));
2039
sem_mypost(RESCACHE);
2042
for (i=0; i<instIdsLen; i++) {
2043
instId = instIds[i];
2044
rc = find_instanceCacheId(instId, &myInstance);
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;
2051
// instance is not in a terminatable state
2054
(*outStatus)[i] = 0;
2057
rc = free_instanceNetwork(myInstance->ccnet.privateMac, myInstance->ccnet.vlan, 1, 1);
2061
// instance is not in cache, try all resources
2064
(*outStatus)[i] = 0;
2069
for (j=start; j<stop && !done; j++) {
2070
if (resourceCacheLocal.resources[j].state == RESUP) {
2072
rc = ncClientCall(ccMeta, 0, NCCALL, resourceCacheLocal.resources[j].ncURL, "ncTerminateInstance", instId, &shutdownState, &previousState);
2074
(*outStatus)[i] = 1;
2075
logprintfl(EUCAWARN, "TerminateInstances(): failed to terminate '%s': instance may not exist any longer\n", instId);
2078
(*outStatus)[i] = 0;
2086
logprintfl(EUCADEBUG,"TerminateInstances(): done.\n");
2093
int setup_shared_buffer(void **buf, char *bufname, size_t bytes, sem_t **lock, char *lockname, int mode) {
2096
// create a lock and grab it
2097
*lock = sem_open(lockname, O_CREAT, 0644, 1);
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);
2105
// if this is the first process to create the config, init to 0
2106
rc = ftruncate(shd, bytes);
2108
shd = shm_open(bufname, O_CREAT | O_RDWR, 0644);
2111
fprintf(stderr, "cannot initialize shared memory segment\n");
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];
2122
tmpstr = getenv(EUCALYPTUS_ENV_VAR_NAME);
2124
snprintf(path, MAX_PATH, "/var/lib/eucalyptus/CC/%s", bufname);
2126
snprintf(path, MAX_PATH, "%s/var/lib/eucalyptus/CC/%s", tmpstr, bufname);
2128
fd = open(path, O_RDWR | O_CREAT, 0600);
2130
fprintf(stderr, "ERROR: cannot open/create '%s' to set up mmapped buffer\n", path);
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);
2139
*buf = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
2141
fprintf(stderr, "ERROR: cannot mmap fd\n");
2151
int initialize(void) {
2158
logprintfl(EUCAERROR, "initialize(): cannot initialize thread\n");
2161
rc = init_localstate();
2164
logprintfl(EUCAERROR, "initialize(): cannot initialize local state\n");
2170
logprintfl(EUCAERROR, "initialize(): cannot initialize from configuration file\n");
2173
if (config->use_tunnels) {
2174
rc = vnetInitTunnels(vnetconfig);
2176
logprintfl(EUCAERROR, "initialize(): cannot initialize tunnels\n");
2180
rc = init_pthreads();
2182
logprintfl(EUCAERROR, "initialize(): cannot initialize background threads\n");
2187
// initialization went well, this thread is now initialized
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
2203
void *monitor_thread(void *in) {
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");
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);
2222
logprintfl(EUCADEBUG, "monitor_thread(): running\n");
2224
rc = refresh_resources(&ccMeta, 60, 1);
2226
logprintfl(EUCAWARN, "monitor_thread(): call to refresh_resources() failed in monitor thread\n");
2229
rc = refresh_instances(&ccMeta, 60, 1);
2231
logprintfl(EUCAWARN, "monitor_thread(): call to refresh_instances() failed in monitor thread\n");
2235
if (config->kick_dhcp) {
2236
rc = vnetKickDHCP(vnetconfig);
2238
logprintfl(EUCAERROR, "monitor_thread(): cannot start DHCP daemon\n");
2240
config->kick_dhcp = 0;
2247
logprintfl(EUCADEBUG, "monitor_thread(): done\n");
2248
sleep(config->ncPollingFrequency);
2253
int init_pthreads() {
2254
// start any background threads
2259
if (config->threads[MONITOR] == 0 || check_process(config->threads[MONITOR], "httpd-cc.conf")) {
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);
2271
monitor_thread(NULL);
2274
config->threads[MONITOR] = pid;
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];
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);
2296
tmpstr = getenv(EUCALYPTUS_ENV_VAR_NAME);
2298
snprintf(home, MAX_PATH, "/");
2300
snprintf(home, MAX_PATH, "%s", tmpstr);
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);
2307
tmpstr = getConfString(configFiles, 2, "LOGLEVEL");
2309
loglevel = EUCADEBUG;
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;}
2318
if (tmpstr) free(tmpstr);
2320
logfile(logFile, loglevel);
2328
int init_thread(void) {
2331
logprintfl(EUCADEBUG, "init_thread(): init=%d %08X %08X %08X %08X\n", init, config, vnetconfig, instanceCache, resourceCache);
2333
// thread has already been initialized
2335
// this thread has not been initialized, set up shared memory segments
2338
locks[INIT] = sem_open("/eucalyptusCCinitLock", O_CREAT, 0644, 1);
2341
locks[NCCALL] = sem_open("/eucalyptusCCncCallLock", O_CREAT, 0644, 4);
2343
if (config == NULL) {
2344
rc = setup_shared_buffer((void **)&config, "/eucalyptusCCConfig", sizeof(ccConfig), &(locks[CONFIG]), "/eucalyptusCCConfigLock", SHARED_FILE);
2346
fprintf(stderr, "init_thread(): Cannot set up shared memory region for ccConfig, exiting...\n");
2352
if (instanceCache == NULL) {
2353
rc = setup_shared_buffer((void **)&instanceCache, "/eucalyptusCCInstanceCache", sizeof(ccInstanceCache), &(locks[INSTCACHE]), "/eucalyptusCCInstanceCacheLock", SHARED_FILE);
2355
fprintf(stderr, "init_thread(): Cannot set up shared memory region for ccInstanceCache, exiting...\n");
2361
if (resourceCache == NULL) {
2362
rc = setup_shared_buffer((void **)&resourceCache, "/eucalyptusCCResourceCache", sizeof(ccResourceCache), &(locks[RESCACHE]), "/eucalyptusCCResourceCacheLock", SHARED_FILE);
2364
fprintf(stderr, "init_thread(): Cannot set up shared memory region for ccResourceCache, exiting...\n");
2370
if (vnetconfig == NULL) {
2371
rc = setup_shared_buffer((void **)&vnetconfig, "/eucalyptusCCVNETConfig", sizeof(vnetConfig), &(locks[VNET]), "/eucalyptusCCVNETConfigLock", SHARED_FILE);
2373
fprintf(stderr, "init_thread(): Cannot set up shared memory region for ccVNETConfig, exiting...\n");
2385
int update_config(void) {
2386
char home[MAX_PATH], *tmpstr=NULL;
2387
ccResource *res=NULL;
2388
int rc, numHosts, ret;
2390
struct stat statbuf;
2398
for (i=0; i<2; i++) {
2399
// stat the config file, update modification time
2400
rc = stat(config->configFiles[i], &statbuf);
2402
if (statbuf.st_mtime > configMtime) {
2403
configMtime = statbuf.st_mtime;
2407
if (configMtime == 0) {
2408
logprintfl(EUCAERROR, "update_config(): could not stat config files (%s,%s)\n", config->configFiles[0], config->configFiles[1]);
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");
2418
rc = refreshNodes(config, &res, &numHosts);
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);
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;
2433
resourceCache->numResources = numHosts;
2434
config->schedState = 0;
2435
memcpy(resourceCache->resources, res, sizeof(ccResource) * numHosts);
2436
sem_mypost(RESCACHE);
2441
config->configMtime = configMtime;
2447
int init_config(void) {
2448
ccResource *res=NULL;
2450
int rc, numHosts, use_wssec, use_tunnels, schedPolicy, idleThresh, wakeThresh, ret, i;
2452
char configFiles[2][MAX_PATH], netPath[MAX_PATH], eucahome[MAX_PATH], policyFile[MAX_PATH], home[MAX_PATH];
2454
time_t configMtime, instanceTimeout, ncPollingFrequency;
2455
struct stat statbuf;
2457
// read in base config information
2458
tmpstr = getenv(EUCALYPTUS_ENV_VAR_NAME);
2460
snprintf(home, MAX_PATH, "/");
2462
snprintf(home, MAX_PATH, "%s", tmpstr);
2465
bzero(configFiles[0], MAX_PATH);
2466
bzero(configFiles[1], MAX_PATH);
2467
bzero(netPath, MAX_PATH);
2468
bzero(policyFile, MAX_PATH);
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);
2476
if (config_init && config->initialized) {
2477
// this means that this thread has already been initialized
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();
2487
// failed to restore network state, continue
2488
logprintfl(EUCAWARN, "init_config(): restoreNetworkState returned false (may be already restored)\n");
2494
logprintfl(EUCADEBUG,"init_config(): initializing CC configuration\n");
2496
// DHCP configuration section
2505
*privInterface=NULL,
2507
*pubSubnetMask=NULL,
2508
*pubBroadcastAddress=NULL,
2513
uint32_t *ips, *nms;
2514
int initFail=0, len;
2516
// DHCP Daemon Configuration Params
2517
daemon = getConfString(configFiles, 2, "VNET_DHCPDAEMON");
2519
logprintfl(EUCAWARN,"init_config(): no VNET_DHCPDAEMON defined in config, using default\n");
2522
dhcpuser = getConfString(configFiles, 2, "VNET_DHCPUSER");
2524
dhcpuser = strdup("root");
2526
logprintfl(EUCAFATAL,"init_config(): Out of memory\n");
2531
pubmode = getConfString(configFiles, 2, "VNET_MODE");
2533
logprintfl(EUCAWARN,"init_config(): VNET_MODE is not defined, defaulting to 'SYSTEM'\n");
2534
pubmode = strdup("SYSTEM");
2536
logprintfl(EUCAFATAL,"init_config(): Out of memory\n");
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");
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");
2570
tmpstr = getConfString(configFiles, 2, "VNET_INTERFACE");
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");
2580
if (privInterface) free(privInterface);
2581
privInterface = strdup(tmpstr);
2582
if (!privInterface) {
2583
logprintfl(EUCAFATAL, "init_config(): out of memory!\n");
2587
if (tmpstr) free(tmpstr);
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");
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");
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");
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");
2613
cloudIp = getConfString(configFiles, 2, "VNET_CLOUDIP");
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");
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);
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);
2657
vnetAddDev(vnetconfig, vnetconfig->privInterface);
2660
char *mac=NULL, *ip=NULL, *ptra=NULL, *toka=NULL, *ptrb=NULL;
2661
toka = strtok_r(pubmacmap, " ", &ptra);
2664
mac = strtok_r(toka, "=", &ptrb);
2665
ip = strtok_r(NULL, "=", &ptrb);
2667
vnetAddHost(vnetconfig, mac, ip, 0, -1);
2669
toka = strtok_r(NULL, " ", &ptra);
2671
vnetKickDHCP(vnetconfig);
2673
} else if (pubips) {
2674
char *ip, *ptra, *toka;
2675
toka = strtok_r(pubips, " ", &ptra);
2679
rc = vnetAddPublicIP(vnetconfig, ip);
2681
logprintfl(EUCAERROR, "init_config(): could not add public IP '%s'\n", ip);
2684
toka = strtok_r(NULL, " ", &ptra);
2687
// detect and populate ips
2688
if (vnetCountLocalIP(vnetconfig) <= 0) {
2690
rc = getdevinfo("all", &ips, &nms, &len);
2692
for (i=0; i<len; i++) {
2694
theip = hex2dot(ips[i]);
2695
if (vnetCheckPublicIP(vnetconfig, theip)) {
2696
vnetAddLocalIP(vnetconfig, ips[i]);
2698
if (theip) free(theip);
2710
tmpstr = getConfString(configFiles, 2, "SCHEDPOLICY");
2713
logprintfl(EUCAWARN,"init_config(): parsing config file (%s) for SCHEDPOLICY, defaulting to GREEDY\n", configFiles[0]);
2714
schedPolicy = SCHEDGREEDY;
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;
2722
if (tmpstr) free(tmpstr);
2724
// powersave options
2725
tmpstr = getConfString(configFiles, 2, "POWER_IDLETHRESH");
2727
logprintfl(EUCAWARN,"init_config(): parsing config file (%s) for POWER_IDLETHRESH, defaulting to 300 seconds\n", configFiles[0]);
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);
2737
if (tmpstr) free(tmpstr);
2739
tmpstr = getConfString(configFiles, 2, "POWER_WAKETHRESH");
2741
logprintfl(EUCAWARN,"init_config(): parsing config file (%s) for POWER_WAKETHRESH, defaulting to 300 seconds\n", configFiles[0]);
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);
2751
if (tmpstr) free(tmpstr);
2753
// some administrative options
2754
tmpstr = getConfString(configFiles, 2, "NC_POLLING_FREQUENCY");
2756
ncPollingFrequency = 6;
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;
2765
if (tmpstr) free(tmpstr);
2767
tmpstr = getConfString(configFiles, 2, "INSTANCE_TIMEOUT");
2769
instanceTimeout = 300;
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;
2778
if (tmpstr) free(tmpstr);
2782
tmpstr = getConfString(configFiles, 2, "ENABLE_WS_SECURITY");
2785
logprintfl(EUCAFATAL,"init_config(): parsing config file (%s) for ENABLE_WS_SECURITY\n", configFiles[0]);
2788
if (!strcmp(tmpstr, "Y")) {
2792
if (tmpstr) free(tmpstr);
2794
// Multi-cluster tunneling
2796
tmpstr = getConfString(configFiles, 2, "DISABLE_TUNNELING");
2798
if (!strcmp(tmpstr, "Y")) {
2802
if (tmpstr) free(tmpstr);
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]);
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);
2825
rc = refreshNodes(config, &res, &numHosts);
2827
logprintfl(EUCAERROR, "init_config(): cannot read list of nodes, check your config file\n");
2831
// update resourceCache
2832
sem_mywait(RESCACHE);
2833
resourceCache->numResources = numHosts;
2835
memcpy(resourceCache->resources, res, sizeof(ccResource) * numHosts);
2838
resourceCache->lastResourceUpdate = 0;
2839
sem_mypost(RESCACHE);
2842
logprintfl(EUCADEBUG,"init_config(): done\n");
2847
int maintainNetworkState() {
2849
time_t startTime, startTimeA;
2851
if (!strcmp(vnetconfig->mode, "MANAGED") || !strcmp(vnetconfig->mode, "MANAGED-NOVLAN")) {
2854
rc = vnetSetupTunnels(vnetconfig);
2857
logprintfl(EUCAERROR, "maintainNetworkState(): failed to setup tunnels during maintainNetworkState()\n");
2861
for (i=2; i<NUMBER_OF_VLANS; i++) {
2862
if (vnetconfig->networks[i].active) {
2864
if (!strcmp(vnetconfig->mode, "MANAGED")) {
2865
snprintf(brname, 32, "eucabr%d", i);
2867
snprintf(brname, 32, "%s", vnetconfig->privInterface);
2869
startTime=time(NULL);
2870
rc = vnetAttachTunnels(vnetconfig, i, brname);
2872
logprintfl(EUCADEBUG, "maintainNetworkState(): failed to attach tunnels for vlan %d during maintainNetworkState()\n", i);
2883
int restoreNetworkState() {
2887
logprintfl(EUCADEBUG, "restoreNetworkState(): restoring network state\n");
2890
// restore iptables state
2891
logprintfl(EUCADEBUG, "restoreNetworkState(): restarting iptables\n");
2892
rc = vnetRestoreTablesFromMemory(vnetconfig);
2894
logprintfl(EUCAERROR, "restoreNetworkState(): cannot restore iptables state\n");
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);
2905
logprintfl(EUCAWARN, "restoreNetworkState(): cannot add ip 169.254.169.254\n");
2908
for (i=1; i<NUMBER_OF_PUBLIC_IPS; i++) {
2909
if (vnetconfig->publicips[i].allocated) {
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);
2917
logprintfl(EUCAWARN, "restoreNetworkState(): cannot add ip %s\n", tmp);
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) {
2928
logprintfl(EUCADEBUG, "restoreNetworkState(): found active network: %d\n", i);
2929
rc = vnetStartNetwork(vnetconfig, i, vnetconfig->users[i].userName, vnetconfig->users[i].netName, &brname);
2931
logprintfl(EUCADEBUG, "restoreNetworkState(): failed to reactivate network: %d", i);
2933
if (brname) free(brname);
2936
// get DHCPD back up and running
2937
logprintfl(EUCADEBUG, "restoreNetworkState(): restarting DHCPD\n");
2938
rc = vnetKickDHCP(vnetconfig);
2940
logprintfl(EUCAERROR, "restoreNetworkState(): cannot start DHCP daemon, please check your network settings\n");
2944
logprintfl(EUCADEBUG, "restoreNetworkState(): done restoring network state\n");
2949
int refreshNodes(ccConfig *config, ccResource **res, int *numHosts) {
2951
char *tmpstr, *ipbuf;
2952
char ncservice[512];
2959
tmpstr = getConfString(config->configFiles, 2, CONFIG_NC_SERVICE);
2962
logprintfl(EUCAFATAL,"refreshNodes(): parsing config files (%s,%s) for NC_SERVICE\n", config->configFiles[1], config->configFiles[0]);
2966
snprintf(ncservice, 512, "%s", tmpstr);
2970
if (tmpstr) free(tmpstr);
2972
tmpstr = getConfString(config->configFiles, 2, CONFIG_NC_PORT);
2975
logprintfl(EUCAFATAL,"refreshNodes(): parsing config files (%s,%s) for NC_PORT\n", config->configFiles[1], config->configFiles[0]);
2979
ncport = atoi(tmpstr);
2981
if (tmpstr) free(tmpstr);
2983
tmpstr = getConfString(config->configFiles, 2, CONFIG_NODES);
2986
logprintfl(EUCAWARN,"refreshNodes(): NODES parameter is missing from config files(%s,%s)\n", config->configFiles[1], config->configFiles[0]);
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);
2998
while(hosts[i] != NULL) {
3000
*res = realloc(*res, sizeof(ccResource) * *numHosts);
3001
bzero(&((*res)[*numHosts-1]), sizeof(ccResource));
3002
snprintf((*res)[*numHosts-1].hostname, 128, "%s", hosts[i]);
3004
ipbuf = host2ip(hosts[i]);
3006
snprintf((*res)[*numHosts-1].ip, 24, "%s", ipbuf);
3008
if (ipbuf) free(ipbuf);
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;
3019
if (hosts) free(hosts);
3020
if (tmpstr) free(tmpstr);
3025
int p=1, status, rc;
3027
// clean up any orphaned child processes
3029
p = waitpid(-1, &status, WNOHANG);
3032
rc = maintainNetworkState();
3034
logprintfl(EUCAERROR, "shawn(): network state maintainance failed\n");
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);
3044
int timeread(int fd, void *buf, size_t bytes, int timeout) {
3049
if (timeout <= 0) timeout = 1;
3054
tv.tv_sec = timeout;
3057
rc = select(fd+1, &rfds, NULL, NULL, &tv);
3060
logprintfl(EUCAERROR, "timeread(): select() timed out for read: timeout=%d\n", timeout);
3063
rc = read(fd, buf, bytes);
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) {
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);
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;
3084
out->lastState = laststate;
3085
out->stateChange = stateChange;
3086
out->idleStart = idleStart;
3092
int free_instanceNetwork(char *mac, int vlan, int force, int dolock) {
3094
unsigned char hexmac[6];
3095
mac2hex(mac, hexmac);
3096
if (!maczero(hexmac)) {
3101
sem_mywait(INSTCACHE);
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")) {
3115
sem_mypost(INSTCACHE);
3119
// remove private network info from system
3121
vnetDisableHost(vnetconfig, mac, NULL, 0);
3122
if (!strcmp(vnetconfig->mode, "MANAGED") || !strcmp(vnetconfig->mode, "MANAGED-NOVLAN")) {
3123
vnetDelHost(vnetconfig, mac, NULL, vlan);
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) {
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);
3138
if (amiURL) strncpy(out->amiURL, amiURL, 512);
3139
if (kernelURL) strncpy(out->kernelURL, kernelURL, 512);
3140
if (ramdiskURL) strncpy(out->ramdiskURL, ramdiskURL, 512);
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);
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);
3153
for (i=0; i<64; i++) {
3154
if (groupNames[i]) {
3155
strncpy(out->groupNames[i], groupNames[i], 32);
3161
memcpy(out->volumes, volumes, sizeof(ncVolume) * EUCA_MAX_VOLUMES);
3163
out->volumesSize = volumesSize;
3164
// if (networkIndex) out->networkIndex = networkIndex;
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);
3172
int pubIpCmp(ccInstance *inst, void *ip) {
3177
if (!strcmp((char *)ip, inst->ccnet.publicIp)) {
3183
int privIpCmp(ccInstance *inst, void *ip) {
3188
if (!strcmp((char *)ip, inst->ccnet.privateIp)) {
3194
int privIpSet(ccInstance *inst, void *ip) {
3199
logprintfl(EUCADEBUG, "privIpSet(): set: %s/%s\n", inst->ccnet.privateIp, (char *)ip);
3200
snprintf(inst->ccnet.privateIp, 24, "%s", (char *)ip);
3204
int pubIpSet(ccInstance *inst, void *ip) {
3209
logprintfl(EUCADEBUG, "pubIpSet(): set: %s/%s\n", inst->ccnet.publicIp, (char *)ip);
3210
snprintf(inst->ccnet.publicIp, 24, "%s", (char *)ip);
3214
int map_instanceCache(int (*match)(ccInstance *, void *), void *matchParam, int (*operate)(ccInstance *, void *), void *operateParam) {
3217
sem_mywait(INSTCACHE);
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);
3228
sem_mypost(INSTCACHE);
3232
void print_instanceCache(void) {
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);
3241
sem_mypost(INSTCACHE);
3244
void print_ccInstance(char *tag, ccInstance *in) {
3245
char *volbuf, *groupbuf;
3248
volbuf = malloc(sizeof(ncVolume)*EUCA_MAX_VOLUMES*2);
3249
bzero(volbuf, sizeof(ncVolume)*EUCA_MAX_VOLUMES*2);
3251
groupbuf = malloc(64*32*2);
3252
bzero(groupbuf, 64*32*2);
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);
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);
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);
3280
void invalidate_instanceCache(void) {
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);
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--;
3297
sem_mypost(INSTCACHE);
3300
int refresh_instanceCache(char *instanceId, ccInstance *in){
3303
if (!instanceId || !in) {
3307
sem_mywait(INSTCACHE);
3309
for (i=0; i<MAXINSTANCES && !done; i++) {
3310
if (!strcmp(instanceCache->instances[i].instanceId, instanceId)) {
3312
memcpy(&(instanceCache->instances[i]), in, sizeof(ccInstance));
3313
instanceCache->lastseen[i] = time(NULL);
3314
sem_mypost(INSTCACHE);
3318
sem_mypost(INSTCACHE);
3320
add_instanceCache(instanceId, in);
3325
int add_instanceCache(char *instanceId, ccInstance *in){
3326
int i, done, firstNull=0;
3328
if (!instanceId || !in) {
3332
sem_mywait(INSTCACHE);
3334
for (i=0; i<MAXINSTANCES && !done; i++) {
3335
if ( (instanceCache->cacheState[i] == INSTVALID ) && (!strcmp(instanceCache->instances[i].instanceId, instanceId))) {
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);
3341
} else if ( instanceCache->cacheState[i] == INSTINVALID ) {
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;
3352
sem_mypost(INSTCACHE);
3356
int del_instanceCacheId(char *instanceId) {
3359
sem_mywait(INSTCACHE);
3360
for (i=0; i<MAXINSTANCES; i++) {
3361
if ( (instanceCache->cacheState[i] == INSTVALID) && (!strcmp(instanceCache->instances[i].instanceId, instanceId))) {
3363
bzero(&(instanceCache->instances[i]), sizeof(ccInstance));
3364
instanceCache->lastseen[i] = 0;
3365
instanceCache->cacheState[i] = INSTINVALID;
3366
instanceCache->numInsts--;
3367
sem_mypost(INSTCACHE);
3371
sem_mypost(INSTCACHE);
3375
int find_instanceCacheId(char *instanceId, ccInstance **out) {
3378
if (!instanceId || !out) {
3382
sem_mywait(INSTCACHE);
3385
for (i=0; i<MAXINSTANCES && !done; i++) {
3386
if (!strcmp(instanceCache->instances[i].instanceId, instanceId)) {
3388
*out = malloc(sizeof(ccInstance));
3390
logprintfl(EUCAFATAL, "find_instanceCacheId(): out of memory!\n");
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);
3399
sem_mypost(INSTCACHE);
3406
int find_instanceCacheIP(char *ip, ccInstance **out) {
3413
sem_mywait(INSTCACHE);
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)) {
3420
*out = malloc(sizeof(ccInstance));
3422
logprintfl(EUCAFATAL, "find_instanceCacheIP(): out of memory!\n");
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);
3432
sem_mypost(INSTCACHE);
3440
void print_resourceCache(void) {
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);
3449
sem_mypost(RESCACHE);
3452
void invalidate_resourceCache(void) {
3455
sem_mywait(RESCACHE);
3457
bzero(resourceCache->cacheState, sizeof(int)*MAXNODES);
3458
resourceCache->numResources = 0;
3459
resourceCache->resourceCacheUpdate = 0;
3461
sem_mypost(RESCACHE);
3465
int refresh_resourceCache(char *host, ccResource *in){
3472
sem_mywait(RESCACHE);
3474
for (i=0; i<MAXNODES && !done; i++) {
3475
if (resourceCache->cacheState[i] == RESVALID) {
3476
if (!strcmp(resourceCache->resources[i].hostname, host)) {
3478
memcpy(&(resourceCache->resources[i]), in, sizeof(ccResource));
3479
sem_mypost(RESCACHE);
3484
sem_mypost(RESCACHE);
3486
add_resourceCache(host, in);
3491
int add_resourceCache(char *host, ccResource *in){
3492
int i, done, firstNull=0;
3498
sem_mywait(RESCACHE);
3500
for (i=0; i<MAXNODES && !done; i++) {
3501
if (resourceCache->cacheState[i] == RESVALID) {
3502
if (!strcmp(resourceCache->resources[i].hostname, host)) {
3504
sem_mypost(RESCACHE);
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);
3515
resourceCache->numResources++;
3516
sem_mypost(RESCACHE);
3520
int del_resourceCacheId(char *host) {
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)) {
3528
bzero(&(resourceCache->resources[i]), sizeof(ccResource));
3529
resourceCache->cacheState[i] = RESINVALID;
3530
resourceCache->numResources--;
3531
sem_mypost(RESCACHE);
3536
sem_mypost(RESCACHE);
3540
int find_resourceCacheId(char *host, ccResource **out) {
3543
if (!host || !out) {
3547
sem_mywait(RESCACHE);
3550
for (i=0; i<MAXNODES && !done; i++) {
3551
if (resourceCache->cacheState[i] == RESVALID) {
3552
if (!strcmp(resourceCache->resources[i].hostname, host)) {
3554
*out = malloc(sizeof(ccResource));
3556
logprintfl(EUCAFATAL, "find_resourceCacheId(): out of memory!\n");
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);
3565
sem_mypost(RESCACHE);
3572
void unlock_exit(int code) {
3575
logprintfl(EUCADEBUG, "unlock_exit(): params: code=%d\n", code);
3577
for (i=0; i<ENDLOCK; i++) {
3579
logprintfl(EUCAWARN, "unlock_exit(): unlocking index '%d'\n", i);
3586
int sem_mywait(int lockno) {
3588
rc = sem_wait(locks[lockno]);
3589
mylocks[lockno] = 1;
3592
int sem_mypost(int lockno) {
3593
mylocks[lockno] = 0;
3594
return(sem_post(locks[lockno]));