/* Copyright (c) 2009 Eucalyptus Systems, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, only version 3 of the License. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Please contact Eucalyptus Systems, Inc., 130 Castilian Dr., Goleta, CA 93101 USA or visit if you need additional information or have any questions. This file may incorporate work covered under the following copyright and permission notice: Software License Agreement (BSD License) Copyright (c) 2008, Regents of the University of California Redistribution and use of this software in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN THE REGENTS’ DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH ANY SUCH LICENSES OR RIGHTS. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "axis2_skel_EucalyptusCC.h" #include #include #include #include #include #include #include #include "data.h" #include "client-marshal.h" #include #define SUPERUSER "eucalyptus" // local globals int config_init=0; int local_init=0; int thread_init=0; int init=0; // to be stored in shared memory ccConfig *config=NULL; ccInstanceCache *instanceCache=NULL; ccResourceCache *resourceCache=NULL; vnetConfig *vnetconfig=NULL; sem_t *locks[ENDLOCK] = {NULL, NULL, NULL, NULL, NULL, NULL}; int mylocks[ENDLOCK] = {0,0,0,0,0,0}; int ncClientCall(ncMetadata *meta, int timeout, int ncLock, char *ncURL, char *ncOp, ...) { va_list al; int pid, rc=0, ret=0, status=0, opFail=0, len, rbytes, i; int filedes[2]; logprintfl(EUCADEBUG, "ncClientCall(%s): called ncURL=%s timeout=%d\n", ncOp, ncURL, timeout); rc = pipe(filedes); if (rc) { logprintfl(EUCAERROR, "ncClientCall(%s): cannot create pipe\n", ncOp); return(1); } va_start(al, ncOp); // grab the lock sem_mywait(ncLock); pid = fork(); if (!pid) { ncStub *ncs; close(filedes[0]); ncs = ncStubCreate(ncURL, NULL, NULL); if (config->use_wssec) { rc = InitWSSEC(ncs->env, ncs->stub, config->policyFile); } logprintfl(EUCADEBUG, "\tncClientCall(%s): ppid=%d client calling '%s'\n", ncOp, getppid(), ncOp); if (!strcmp(ncOp, "ncGetConsoleOutput")) { // args: char *instId char *instId = va_arg(al, char *); char **consoleOutput=va_arg(al, char **); rc = ncGetConsoleOutputStub(ncs, meta, instId, consoleOutput); if (timeout && consoleOutput) { if (!rc && *consoleOutput) { len = strlen(*consoleOutput) + 1; rc = write(filedes[1], &len, sizeof(int)); rc = write(filedes[1], *consoleOutput, sizeof(char) * len); rc = 0; } else { len = 0; rc = write(filedes[1], &len, sizeof(int)); rc = 1; } } } else if (!strcmp(ncOp, "ncAttachVolume")) { char *instanceId = va_arg(al, char *); char *volumeId = va_arg(al, char *); char *remoteDev = va_arg(al, char *); char *localDev = va_arg(al, char *); rc = ncAttachVolumeStub(ncs, meta, instanceId, volumeId, remoteDev, localDev); } else if (!strcmp(ncOp, "ncDetachVolume")) { char *instanceId = va_arg(al, char *); char *volumeId = va_arg(al, char *); char *remoteDev = va_arg(al, char *); char *localDev = va_arg(al, char *); int force = va_arg(al, int); rc = ncDetachVolumeStub(ncs, meta, instanceId, volumeId, remoteDev, localDev, force); } else if (!strcmp(ncOp, "ncPowerDown")) { rc = ncPowerDownStub(ncs, meta); } else if (!strcmp(ncOp, "ncRebootInstance")) { char *instId = va_arg(al, char *); rc = ncRebootInstanceStub(ncs, meta, instId); } else if (!strcmp(ncOp, "ncTerminateInstance")) { char *instId = va_arg(al, char *); int *shutdownState = va_arg(al, int *); int *previousState = va_arg(al, int *); rc = ncTerminateInstanceStub(ncs, meta, instId, shutdownState, previousState); if (timeout) { if (!rc) { len = 2; rc = write(filedes[1], &len, sizeof(int)); rc = write(filedes[1], shutdownState, sizeof(int)); rc = write(filedes[1], previousState, sizeof(int)); rc = 0; } else { len = 0; rc = write(filedes[1], &len, sizeof(int)); rc = 1; } } } else if (!strcmp(ncOp, "ncStartNetwork")) { char **peers = va_arg(al, char **); int peersLen = va_arg(al, int); int port = va_arg(al, int); int vlan = va_arg(al, int); char **outStatus = va_arg(al, char **); rc = ncStartNetworkStub(ncs, meta, peers, peersLen, port, vlan, outStatus); if (timeout && outStatus) { if (!rc && *outStatus) { len = strlen(*outStatus) + 1; rc = write(filedes[1], &len, sizeof(int)); rc = write(filedes[1], *outStatus, sizeof(char) * len); rc = 0; } else { len = 0; rc = write(filedes[1], &len, sizeof(int)); rc = 1; } } } else if (!strcmp(ncOp, "ncRunInstance")) { char *instId = va_arg(al, char *); char *reservationId = va_arg(al, char *); virtualMachine *ncvm = va_arg(al, virtualMachine *); char *imageId = va_arg(al, char *); char *imageURL = va_arg(al, char *); char *kernelId = va_arg(al, char *); char *kernelURL = va_arg(al, char *); char *ramdiskId = va_arg(al, char *); char *ramdiskURL = va_arg(al, char *); char *keyName = va_arg(al, char *); netConfig *ncnet = va_arg(al, netConfig *); char *userData = va_arg(al, char *); char *launchIndex = va_arg(al, char *); char **netNames = va_arg(al, char **); int netNamesLen = va_arg(al, int); ncInstance **outInst = va_arg(al, ncInstance **); rc = ncRunInstanceStub(ncs, meta, instId, reservationId, ncvm, imageId, imageURL, kernelId, kernelURL, ramdiskId, ramdiskURL, keyName, ncnet, userData, launchIndex, netNames, netNamesLen, outInst); if (timeout && outInst) { if (!rc && *outInst) { len = sizeof(ncInstance); rc = write(filedes[1], &len, sizeof(int)); rc = write(filedes[1], *outInst, sizeof(ncInstance)); rc = 0; } else { len = 0; rc = write(filedes[1], &len, sizeof(int)); rc = 1; } } } else if (!strcmp(ncOp, "ncDescribeInstances")) { char **instIds = va_arg(al, char **); int instIdsLen = va_arg(al, int); ncInstance ***ncOutInsts=va_arg(al, ncInstance ***); int *ncOutInstsLen= va_arg(al, int *); rc = ncDescribeInstancesStub(ncs, meta, instIds, instIdsLen, ncOutInsts, ncOutInstsLen); if (timeout && ncOutInsts && ncOutInstsLen) { if (!rc) { len = *ncOutInstsLen; rc = write(filedes[1], &len, sizeof(int)); for (i=0; iuserId : "UNSET"), SP(volumeId), SP(instanceId), SP(remoteDev), SP(localDev)); if (!volumeId || !instanceId || !remoteDev || !localDev) { logprintfl(EUCAERROR, "AttachVolume(): bad input params\n"); return(1); } sem_mywait(RESCACHE); memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache)); sem_mypost(RESCACHE); rc = find_instanceCacheId(instanceId, &myInstance); if (!rc) { // found the instance in the cache if (myInstance) { start = myInstance->ncHostIdx; stop = start+1; free(myInstance); } } else { start = 0; stop = resourceCacheLocal.numResources; } done=0; for (j=start; juserId : "UNSET"), SP(volumeId), SP(instanceId), SP(remoteDev), SP(localDev)); if (!volumeId || !instanceId || !remoteDev || !localDev) { logprintfl(EUCAERROR, "DetachVolume(): bad input params\n"); return(1); } sem_mywait(RESCACHE); memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache)); sem_mypost(RESCACHE); rc = find_instanceCacheId(instanceId, &myInstance); if (!rc) { // found the instance in the cache if (myInstance) { start = myInstance->ncHostIdx; stop = start+1; free(myInstance); } } else { start = 0; stop = resourceCacheLocal.numResources; } for (j=start; juserId), SP(type), namedLen, netLen, SP(destName), SP(destUserName), SP(protocol), minPort, maxPort); if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) { fail = 0; } else { if (destUserName == NULL) { destUserName = meta->userId; } sem_mywait(VNET); fail=0; for (i=0; imode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) { return(0); } sem_mywait(VNET); rc = vnetFlushTable(vnetconfig, ccMeta->userId, destName); sem_mypost(VNET); return(rc); } int doAssignAddress(ncMetadata *ccMeta, char *src, char *dst) { int rc, allocated, addrdevno, ret; char cmd[MAX_PATH]; ccInstance *myInstance=NULL; rc = initialize(); if (rc) { return(1); } logprintfl(EUCAINFO,"AssignAddress(): called\n"); logprintfl(EUCADEBUG,"AssignAddress(): params: src=%s, dst=%s\n", SP(src), SP(dst)); if (!src || !dst || !strcmp(src, "0.0.0.0") || !strcmp(dst, "0.0.0.0")) { logprintfl(EUCADEBUG, "AssignAddress(): bad input params\n"); return(1); } ret = 0; if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) { ret = 0; } else { sem_mywait(VNET); rc = vnetGetPublicIP(vnetconfig, src, NULL, &allocated, &addrdevno); if (rc) { logprintfl(EUCAERROR,"AssignAddress(): failed to retrieve publicip record %s\n", src); ret = 1; } else { if (!allocated) { snprintf(cmd, MAX_PATH, "%s/usr/lib/eucalyptus/euca_rootwrap ip addr add %s/32 dev %s", config->eucahome, src, vnetconfig->pubInterface); logprintfl(EUCADEBUG,"running cmd %s\n", cmd); rc = system(cmd); rc = rc>>8; if (rc && (rc != 2)) { logprintfl(EUCAERROR,"AssignAddress(): cmd '%s' failed\n", cmd); ret = 1; } else { rc = vnetAssignAddress(vnetconfig, src, dst); if (rc) { logprintfl(EUCAERROR,"AssignAddress(): vnetAssignAddress() failed\n"); ret = 1; } else { rc = vnetAllocatePublicIP(vnetconfig, src, dst); if (rc) { logprintfl(EUCAERROR,"AssignAddress(): vnetAllocatePublicIP() failed\n"); ret = 1; } } } } else { logprintfl(EUCAWARN,"AssignAddress(): ip %s is already assigned, ignoring\n", src); ret = 0; } } sem_mypost(VNET); } if (!ret) { // everything worked, update instance cache rc = map_instanceCache(privIpCmp, dst, pubIpSet, src); if (rc) { logprintfl(EUCAERROR, "AssignAddress(): map_instanceCache() failed to assign %s->%s\n", dst, src); } } logprintfl(EUCADEBUG,"AssignAddress(): done\n"); shawn(); return(ret); } int doDescribePublicAddresses(ncMetadata *ccMeta, publicip **outAddresses, int *outAddressesLen) { int rc, ret; rc = initialize(); if (rc) { return(1); } logprintfl(EUCAINFO, "DescribePublicAddresses(): called\n"); logprintfl(EUCADEBUG, "DescribePublicAddresses(): params: userId=%s\n", SP(ccMeta ? ccMeta->userId : "UNSET")); ret=0; if (!strcmp(vnetconfig->mode, "MANAGED") || !strcmp(vnetconfig->mode, "MANAGED-NOVLAN")) { *outAddresses = vnetconfig->publicips; *outAddressesLen = NUMBER_OF_PUBLIC_IPS; } else { *outAddresses = NULL; *outAddressesLen = 0; ret=2; } logprintfl(EUCADEBUG, "DescribePublicAddresses(): done\n"); shawn(); return(ret); } int doUnassignAddress(ncMetadata *ccMeta, char *src, char *dst) { int rc, allocated, addrdevno, ret; char cmd[MAX_PATH]; ccInstance *myInstance=NULL; rc = initialize(); if (rc) { return(1); } logprintfl(EUCAINFO,"UnassignAddress(): called\n"); logprintfl(EUCADEBUG,"UnassignAddress(): params: userId=%s, src=%s, dst=%s\n", SP(ccMeta ? ccMeta->userId : "UNSET"), SP(src), SP(dst)); if (!src || !dst || !strcmp(src, "0.0.0.0") || !strcmp(dst, "0.0.0.0")) { logprintfl(EUCADEBUG, "UnassignAddress(): bad input params\n"); return(1); } if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) { ret = 0; } else { sem_mywait(VNET); ret=0; rc = vnetGetPublicIP(vnetconfig, src, NULL, &allocated, &addrdevno); if (rc) { logprintfl(EUCAERROR,"UnassignAddress(): failed to find publicip to unassign (%s)\n", src); ret=1; } else { if (allocated && dst) { rc = vnetUnassignAddress(vnetconfig, src, dst); if (rc) { logprintfl(EUCAWARN,"vnetUnassignAddress() failed %d: %s/%s\n", rc, src, dst); } rc = vnetDeallocatePublicIP(vnetconfig, src, dst); if (rc) { logprintfl(EUCAWARN,"vnetDeallocatePublicIP() failed %d: %s\n", rc, src); } } snprintf(cmd, MAX_PATH, "%s/usr/lib/eucalyptus/euca_rootwrap ip addr del %s/32 dev %s", config->eucahome, src, vnetconfig->pubInterface); logprintfl(EUCADEBUG, "UnassignAddress(): running cmd '%s'\n", cmd); rc = system(cmd); if (rc) { logprintfl(EUCAWARN,"UnassignAddress(): cmd failed '%s'\n", cmd); } } sem_mypost(VNET); } if (!ret) { // refresh instance cache rc = map_instanceCache(pubIpCmp, src, pubIpSet, "0.0.0.0"); if (rc) { logprintfl(EUCAERROR, "UnassignAddress(): map_instanceCache() failed to assign %s->%s\n", dst, src); } } logprintfl(EUCADEBUG,"UnassignAddress(): done\n"); shawn(); return(ret); } int doStopNetwork(ncMetadata *ccMeta, char *netName, int vlan) { int rc, ret; rc = initialize(); if (rc) { return(1); } logprintfl(EUCAINFO, "StopNetwork(): called\n"); logprintfl(EUCADEBUG, "StopNetwork(): params: userId=%s, netName=%s, vlan=%d\n", SP(ccMeta ? ccMeta->userId : "UNSET"), SP(netName), vlan); if (!ccMeta || !netName || vlan < 0) { logprintfl(EUCAERROR, "StopNetwork(): bad input params\n"); } if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) { ret = 0; } else { sem_mywait(VNET); if(ccMeta != NULL) { rc = vnetStopNetwork(vnetconfig, vlan, ccMeta->userId, netName); } ret = rc; sem_mypost(VNET); } logprintfl(EUCADEBUG,"StopNetwork(): done\n"); shawn(); return(ret); } int doDescribeNetworks(ncMetadata *ccMeta, char *nameserver, char **ccs, int ccsLen, vnetConfig *outvnetConfig) { int rc, i, j; rc = initialize(); if (rc) { return(1); } logprintfl(EUCAINFO, "DescribeNetworks(): called\n"); logprintfl(EUCADEBUG, "DescribeNetworks(): params: userId=%s, nameserver=%s, ccsLen=%d\n", SP(ccMeta ? ccMeta->userId : "UNSET"), SP(nameserver), ccsLen); sem_mywait(VNET); if (nameserver) { vnetconfig->euca_ns = dot2hex(nameserver); } if (!strcmp(vnetconfig->mode, "MANAGED") || !strcmp(vnetconfig->mode, "MANAGED-NOVLAN")) { rc = vnetSetCCS(vnetconfig, ccs, ccsLen); rc = vnetSetupTunnels(vnetconfig); } memcpy(outvnetConfig, vnetconfig, sizeof(vnetConfig)); sem_mypost(VNET); logprintfl(EUCADEBUG, "DescribeNetworks(): done\n"); shawn(); return(0); } int doStartNetwork(ncMetadata *ccMeta, char *netName, int vlan, char *nameserver, char **ccs, int ccsLen) { int rc, ret; time_t op_start; char *brname; op_start = time(NULL); rc = initialize(); if (rc) { return(1); } logprintfl(EUCAINFO, "StartNetwork(): called\n"); 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); if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) { ret = 0; } else { sem_mywait(VNET); if (nameserver) { vnetconfig->euca_ns = dot2hex(nameserver); } rc = vnetSetCCS(vnetconfig, ccs, ccsLen); rc = vnetSetupTunnels(vnetconfig); brname = NULL; rc = vnetStartNetwork(vnetconfig, vlan, ccMeta->userId, netName, &brname); if (brname) free(brname); sem_mypost(VNET); if (rc) { logprintfl(EUCAERROR,"StartNetwork(): vnetStartNetwork() failed (%d)\n", rc); ret = 1; } else { ret = 0; } } logprintfl(EUCADEBUG,"StartNetwork(): done\n"); shawn(); return(ret); } int doDescribeResources(ncMetadata *ccMeta, virtualMachine **ccvms, int vmLen, int **outTypesMax, int **outTypesAvail, int *outTypesLen, char ***outServiceTags, int *outServiceTagsLen) { int i; int rc, diskpool, mempool, corepool; int j; ccResource *res; time_t op_start; ccResourceCache resourceCacheLocal; char strbuf[4096]; logprintfl(EUCAINFO,"DescribeResources(): called\n"); logprintfl(EUCADEBUG,"DescribeResources(): params: userId=%s, vmLen=%d\n", SP(ccMeta ? ccMeta->userId : "UNSET"), vmLen); op_start = time(NULL); rc = initialize(); if (rc) { return(1); } if (outTypesMax == NULL || outTypesAvail == NULL || outTypesLen == NULL || outServiceTags == NULL || outServiceTagsLen == NULL) { // input error return(1); } *outTypesMax = NULL; *outTypesAvail = NULL; *outTypesMax = malloc(sizeof(int) * vmLen); *outTypesAvail = malloc(sizeof(int) * vmLen); if (*outTypesMax == NULL || *outTypesAvail == NULL) { logprintfl(EUCAERROR,"DescribeResources(): out of memory\n"); unlock_exit(1); } bzero(*outTypesMax, sizeof(int) * vmLen); bzero(*outTypesAvail, sizeof(int) * vmLen); *outTypesLen = vmLen; for (i=0; iavailMemory; diskpool = res->availDisk; corepool = res->availCores; mempool -= (*ccvms)[j].mem; diskpool -= (*ccvms)[j].disk; corepool -= (*ccvms)[j].cores; while (mempool >= 0 && diskpool >= 0 && corepool >= 0) { (*outTypesAvail)[j]++; mempool -= (*ccvms)[j].mem; diskpool -= (*ccvms)[j].disk; corepool -= (*ccvms)[j].cores; } mempool = res->maxMemory; diskpool = res->maxDisk; corepool = res->maxCores; mempool -= (*ccvms)[j].mem; diskpool -= (*ccvms)[j].disk; corepool -= (*ccvms)[j].cores; while (mempool >= 0 && diskpool >= 0 && corepool >= 0) { (*outTypesMax)[j]++; mempool -= (*ccvms)[j].mem; diskpool -= (*ccvms)[j].disk; corepool -= (*ccvms)[j].cores; } } } } if (vmLen >= 5) { 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]); } logprintfl(EUCADEBUG,"DescribeResources(): done\n"); shawn(); return(0); } int changeState(ccResource *in, int newstate) { if (in == NULL) return(1); if (in->state == newstate) return(0); in->lastState = in->state; in->state = newstate; in->stateChange = time(NULL); in->idleStart = 0; return(0); } int refresh_resources(ncMetadata *ccMeta, int timeout, int dolock) { int i, rc, nctimeout; int status, ret=0; int filedes[2]; time_t op_start; ncStub *ncs; ncResource *ncResDst=NULL; ccResourceCache resourceCacheLocal; if (timeout <= 0) timeout = 1; op_start = time(NULL); logprintfl(EUCAINFO,"refresh_resources(): called\n"); rc = update_config(); if (rc) { logprintfl(EUCAWARN, "refresh_resources(): bad return from update_config(), check your config file\n"); } // critical NC call section sem_mywait(RESCACHE); memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache)); sem_mypost(RESCACHE); for (i=0; iwakeThresh)) { logprintfl(EUCADEBUG, "refresh_resources(): resource still waking up (%d more seconds until marked as down)\n", config->wakeThresh - (time(NULL) - resourceCacheLocal.resources[i].stateChange)); } else{ logprintfl(EUCAERROR,"refresh_resources(): bad return from ncDescribeResource(%s) (%d)\n", resourceCacheLocal.resources[i].hostname, rc); resourceCacheLocal.resources[i].maxMemory = 0; resourceCacheLocal.resources[i].availMemory = 0; resourceCacheLocal.resources[i].maxDisk = 0; resourceCacheLocal.resources[i].availDisk = 0; resourceCacheLocal.resources[i].maxCores = 0; resourceCacheLocal.resources[i].availCores = 0; changeState(&(resourceCacheLocal.resources[i]), RESDOWN); } } else { 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); resourceCacheLocal.resources[i].maxMemory = ncResDst->memorySizeMax; resourceCacheLocal.resources[i].availMemory = ncResDst->memorySizeAvailable; resourceCacheLocal.resources[i].maxDisk = ncResDst->diskSizeMax; resourceCacheLocal.resources[i].availDisk = ncResDst->diskSizeAvailable; resourceCacheLocal.resources[i].maxCores = ncResDst->numberOfCoresMax; resourceCacheLocal.resources[i].availCores = ncResDst->numberOfCoresAvailable; changeState(&(resourceCacheLocal.resources[i]), RESUP); } } else { logprintfl(EUCADEBUG, "refresh_resources(): resource asleep/running instances (%d), skipping resource update\n", resourceCacheLocal.resources[i].running); } // try to discover the mac address of the resource if (resourceCacheLocal.resources[i].mac[0] == '\0' && resourceCacheLocal.resources[i].ip[0] != '\0') { char *mac; rc = ip2mac(vnetconfig, resourceCacheLocal.resources[i].ip, &mac); if (!rc) { strncpy(resourceCacheLocal.resources[i].mac, mac, 24); free(mac); logprintfl(EUCADEBUG, "refresh_resources(): discovered MAC '%s' for host %s(%s)\n", resourceCacheLocal.resources[i].mac, resourceCacheLocal.resources[i].hostname, resourceCacheLocal.resources[i].ip); } } if (ncResDst) free(ncResDst); } sem_mywait(RESCACHE); memcpy(resourceCache, &resourceCacheLocal, sizeof(ccResourceCache)); sem_mypost(RESCACHE); logprintfl(EUCADEBUG,"refresh_resources(): done\n"); return(0); } int refresh_instances(ncMetadata *ccMeta, int timeout, int dolock) { ccInstance *myInstance=NULL; int i, k, numInsts = 0, found, ncOutInstsLen, rc, pid, nctimeout; time_t op_start; ncInstance **ncOutInsts=NULL; ncStub *ncs; ccResourceCache resourceCacheLocal; op_start = time(NULL); logprintfl(EUCAINFO,"refresh_instances(): called\n"); // critical NC call section sem_mywait(RESCACHE); memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache)); sem_mypost(RESCACHE); invalidate_instanceCache(); for (i=0; iidleThresh); if (!resourceCacheLocal.resources[i].idleStart) { resourceCacheLocal.resources[i].idleStart = time(NULL); } else if ((time(NULL) - resourceCacheLocal.resources[i].idleStart) > config->idleThresh) { // call powerdown if (powerDown(ccMeta, &(resourceCacheLocal.resources[i]))) { logprintfl(EUCAWARN, "refresh_instances(): powerDown for %s failed\n", resourceCacheLocal.resources[i].hostname); } } } else { resourceCacheLocal.resources[i].idleStart = 0; } // populate instanceCache for (j=0; jinstanceId, ncOutInsts[j]->stateName, j); numInsts++; // grab instance from cache, if available. otherwise, start from scratch rc = find_instanceCacheId(ncOutInsts[j]->instanceId, &myInstance); if (rc || !myInstance) { myInstance = malloc(sizeof(ccInstance)); if (!myInstance) { logprintfl(EUCAFATAL, "refresh_instances(): out of memory!\n"); unlock_exit(1); } bzero(myInstance, sizeof(ccInstance)); } // update CC instance with instance state from NC rc = ccInstance_to_ncInstance(myInstance, ncOutInsts[j]); // instance info that the CC maintains myInstance->ncHostIdx = i; strncpy(myInstance->serviceTag, resourceCacheLocal.resources[i].ncURL, 64); { char *ip=NULL; if (!strcmp(myInstance->ccnet.publicIp, "0.0.0.0")) { if (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) { rc = mac2ip(vnetconfig, myInstance->ccnet.privateMac, &ip); if (!rc) { strncpy(myInstance->ccnet.publicIp, ip, 24); } } } if (ip) free(ip); ip=NULL; if (!strcmp(myInstance->ccnet.privateIp, "0.0.0.0")) { rc = mac2ip(vnetconfig, myInstance->ccnet.privateMac, &ip); if (!rc) { strncpy(myInstance->ccnet.privateIp, ip, 24); } } if (ip) free(ip); } refresh_instanceCache(myInstance->instanceId, myInstance); logprintfl(EUCADEBUG, "refresh_instances(): storing instance state: %s/%s/%s/%s\n", myInstance->instanceId, myInstance->state, myInstance->ccnet.publicIp, myInstance->ccnet.privateIp); print_ccInstance("refresh_instances(): ", myInstance); if (myInstance) free(myInstance); } } } if (ncOutInsts) { for (j=0; juserId : "UNSET"), instIdsLen); op_start = time(NULL); rc = initialize(); if (rc) { return(1); } *outInsts = NULL; *outInstsLen = 0; sem_mywait(INSTCACHE); count=0; if (instanceCache->numInsts) { *outInsts = malloc(sizeof(ccInstance) * instanceCache->numInsts); if (!*outInsts) { logprintfl(EUCAFATAL, "doDescribeInstances(): out of memory!\n"); unlock_exit(1); } for (i=0; icacheState[i] == INSTVALID) { if (count >= instanceCache->numInsts) { logprintfl(EUCAWARN, "doDescribeInstances(): found more instances than reported by numInsts, will only report a subset of instances\n"); count=0; } memcpy( &((*outInsts)[count]), &(instanceCache->instances[i]), sizeof(ccInstance)); count++; } } *outInstsLen = instanceCache->numInsts; } sem_mypost(INSTCACHE); for (i=0; i< (*outInstsLen) ; i++) { 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); } logprintfl(EUCADEBUG,"DescribeInstances(): done\n"); shawn(); return(0); } int powerUp(ccResource *res) { int rc,ret,len, i; char cmd[MAX_PATH], *bc=NULL; uint32_t *ips=NULL, *nms=NULL; if (config->schedPolicy != SCHEDPOWERSAVE) { return(0); } rc = getdevinfo(vnetconfig->privInterface, &ips, &nms, &len); if (rc) { ips = malloc(sizeof(uint32_t)); if (!ips) { logprintfl(EUCAFATAL, "powerUp(): out of memory!\n"); unlock_exit(1); } nms = malloc(sizeof(uint32_t)); if (!nms) { logprintfl(EUCAFATAL, "powerUp(): out of memory!\n"); unlock_exit(1); } ips[0] = 0xFFFFFFFF; nms[0] = 0xFFFFFFFF; len = 1; } for (i=0; ihostname, res->ip, res->mac); // try to wake up res // broadcast bc = hex2dot((0xFFFFFFFF - nms[i]) | (ips[i] & nms[i])); rc = 0; ret = 0; if (strcmp(res->mac, "00:00:00:00:00:00")) { snprintf(cmd, MAX_PATH, "%s/usr/lib/eucalyptus/euca_rootwrap powerwake -b %s %s", vnetconfig->eucahome, bc, res->mac); } else if (strcmp(res->ip, "0.0.0.0")) { snprintf(cmd, MAX_PATH, "%s/usr/lib/eucalyptus/euca_rootwrap powerwake -b %s %s", vnetconfig->eucahome, bc, res->ip); } else { ret = rc = 1; } if (bc) free(bc); if (!rc) { logprintfl(EUCAINFO, "powerUp(): waking up powered off host %s(%s/%s): %s\n", res->hostname, res->ip, res->mac, cmd); rc = system(cmd); rc = rc>>8; if (rc) { logprintfl(EUCAERROR, "powerUp(): cmd failed: %d\n", rc); ret = 1; } else { logprintfl(EUCAERROR, "powerUp(): cmd success: %d\n", rc); changeState(res, RESWAKING); ret = 0; } } } if (ips) free(ips); if (nms) free(nms); return(ret); } int powerDown(ncMetadata *ccMeta, ccResource *node) { int pid, rc, status, timeout; ncStub *ncs=NULL; time_t op_start; if (config->schedPolicy != SCHEDPOWERSAVE) { node->idleStart = 0; return(0); } op_start = time(NULL); logprintfl(EUCAINFO, "powerDown(): sending powerdown to node: %s, %s\n", node->hostname, node->ncURL); timeout = ncGetTimeout(op_start, OP_TIMEOUT, 1, 1); rc = ncClientCall(ccMeta, timeout, NCCALL, node->ncURL, "ncPowerDown"); if (rc == 0) { changeState(node, RESASLEEP); } return(rc); } int ccInstance_to_ncInstance(ccInstance *dst, ncInstance *src) { int i; strncpy(dst->instanceId, src->instanceId, 16); strncpy(dst->reservationId, src->reservationId, 16); strncpy(dst->ownerId, src->userId, 16); strncpy(dst->amiId, src->imageId, 16); strncpy(dst->kernelId, src->kernelId, 16); strncpy(dst->ramdiskId, src->ramdiskId, 16); strncpy(dst->keyName, src->keyName, 1024); strncpy(dst->launchIndex, src->launchIndex, 64); strncpy(dst->userData, src->userData, 4096); strncpy(dst->state, src->stateName, 16); dst->ts = src->launchTime; dst->ccnet.vlan = src->ncnet.vlan; dst->ccnet.networkIndex = src->ncnet.networkIndex; strncpy(dst->ccnet.privateMac, src->ncnet.privateMac, 24); if (strcmp(src->ncnet.publicIp, "0.0.0.0") || dst->ccnet.publicIp[0] == '\0') strncpy(dst->ccnet.publicIp, src->ncnet.publicIp, 24); if (strcmp(src->ncnet.privateIp, "0.0.0.0") || dst->ccnet.privateIp[0] == '\0') strncpy(dst->ccnet.privateIp, src->ncnet.privateIp, 24); for (i=0; i < src->groupNamesSize && i < 64; i++) { snprintf(dst->groupNames[i], 32, "%s", src->groupNames[i]); } memcpy(dst->volumes, src->volumes, sizeof(ncVolume) * EUCA_MAX_VOLUMES); dst->volumesSize = src->volumesSize; memcpy(&(dst->ccvm), &(src->params), sizeof(virtualMachine)); return(0); } int schedule_instance(virtualMachine *vm, char *targetNode, int *outresid) { int ret; ncMetadata ccMeta; if (targetNode != NULL) { ret = schedule_instance_explicit(vm, targetNode, outresid); } else if (config->schedPolicy == SCHEDGREEDY) { ret = schedule_instance_greedy(vm, outresid); } else if (config->schedPolicy == SCHEDROUNDROBIN) { ret = schedule_instance_roundrobin(vm, outresid); } else if (config->schedPolicy == SCHEDPOWERSAVE) { ret = schedule_instance_greedy(vm, outresid); } else { ret = schedule_instance_greedy(vm, outresid); } return(ret); } int schedule_instance_roundrobin(virtualMachine *vm, int *outresid) { int i, done, start, found, resid=0; ccResource *res; *outresid = 0; logprintfl(EUCADEBUG, "schedule(): scheduler using ROUNDROBIN policy to find next resource\n"); // find the best 'resource' on which to run the instance done=found=0; start = config->schedState; i = start; logprintfl(EUCADEBUG, "schedule(): scheduler state starting at resource %d\n", config->schedState); while(!done) { int mem, disk, cores; res = &(resourceCache->resources[i]); if (res->state != RESDOWN) { mem = res->availMemory - vm->mem; disk = res->availDisk - vm->disk; cores = res->availCores - vm->cores; if (mem >= 0 && disk >= 0 && cores >= 0) { resid = i; found=1; done++; } } i++; if (i >= resourceCache->numResources) { i = 0; } if (i == start) { done++; } } if (!found) { // didn't find a resource return(1); } *outresid = resid; config->schedState = i; logprintfl(EUCADEBUG, "schedule(): scheduler state finishing at resource %d\n", config->schedState); return(0); } int schedule_instance_explicit(virtualMachine *vm, char *targetNode, int *outresid) { int i, rc, done, resid, sleepresid; ccResource *res; *outresid = 0; logprintfl(EUCADEBUG, "schedule(): scheduler using EXPLICIT policy to run VM on target node '%s'\n", targetNode); // find the best 'resource' on which to run the instance resid = sleepresid = -1; done=0; for (i=0; inumResources && !done; i++) { int mem, disk, cores; res = &(resourceCache->resources[i]); if (!strcmp(res->hostname, targetNode)) { done++; if (res->state == RESUP) { mem = res->availMemory - vm->mem; disk = res->availDisk - vm->disk; cores = res->availCores - vm->cores; if (mem >= 0 && disk >= 0 && cores >= 0) { resid = i; } } else if (res->state == RESASLEEP) { mem = res->availMemory - vm->mem; disk = res->availDisk - vm->disk; cores = res->availCores - vm->cores; if (mem >= 0 && disk >= 0 && cores >= 0) { sleepresid = i; } } } } if (resid == -1 && sleepresid == -1) { // target resource is unavailable return(1); } if (resid != -1) { res = &(resourceCache->resources[resid]); *outresid = resid; } else if (sleepresid != -1) { res = &(resourceCache->resources[sleepresid]); *outresid = sleepresid; } if (res->state == RESASLEEP) { rc = powerUp(res); } return(0); } int schedule_instance_greedy(virtualMachine *vm, int *outresid) { int i, rc, done, resid, sleepresid; ccResource *res; *outresid = 0; if (config->schedPolicy == SCHEDGREEDY) { logprintfl(EUCADEBUG, "schedule(): scheduler using GREEDY policy to find next resource\n"); } else if (config->schedPolicy == SCHEDPOWERSAVE) { logprintfl(EUCADEBUG, "schedule(): scheduler using POWERSAVE policy to find next resource\n"); } // find the best 'resource' on which to run the instance resid = sleepresid = -1; done=0; for (i=0; inumResources && !done; i++) { int mem, disk, cores; res = &(resourceCache->resources[i]); if ((res->state == RESUP || res->state == RESWAKING) && resid == -1) { mem = res->availMemory - vm->mem; disk = res->availDisk - vm->disk; cores = res->availCores - vm->cores; if (mem >= 0 && disk >= 0 && cores >= 0) { resid = i; done++; } } else if (res->state == RESASLEEP && sleepresid == -1) { mem = res->availMemory - vm->mem; disk = res->availDisk - vm->disk; cores = res->availCores - vm->cores; if (mem >= 0 && disk >= 0 && cores >= 0) { sleepresid = i; } } } if (resid == -1 && sleepresid == -1) { // didn't find a resource return(1); } if (resid != -1) { res = &(resourceCache->resources[resid]); *outresid = resid; } else if (sleepresid != -1) { res = &(resourceCache->resources[sleepresid]); *outresid = sleepresid; } if (res->state == RESASLEEP) { rc = powerUp(res); } return(0); } 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) { int rc=0, i=0, done=0, runCount=0, resid=0, foundnet=0, error=0, networkIdx=0, nidx=0, thenidx=0; ccInstance *myInstance=NULL, *retInsts=NULL; char instId[16]; time_t op_start=0; ccResource *res=NULL; char mac[32], privip[32], pubip[32]; ncInstance *outInst=NULL; virtualMachine ncvm; netConfig ncnet; ncStub *ncs=NULL; op_start = time(NULL); rc = initialize(); if (rc) { return(1); } logprintfl(EUCAINFO,"RunInstances(): called\n"); 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)); *outInstsLen = 0; if (!ccvm) { logprintfl(EUCAERROR,"RunInstances(): invalid ccvm\n"); return(-1); } if (minCount <= 0 || maxCount <= 0 || instIdsLen < maxCount) { logprintfl(EUCAERROR,"RunInstances(): bad min or max count, or not enough instIds (%d, %d, %d)\n", minCount, maxCount, instIdsLen); return(-1); } // check health of the networkIndexList if ( (!strcmp(vnetconfig->mode, "SYSTEM") || !strcmp(vnetconfig->mode, "STATIC")) || networkIndexList == NULL) { // disabled nidx=-1; } else { if ( (networkIndexListLen < minCount) || (networkIndexListLen > maxCount) ) { logprintfl(EUCAERROR, "RunInstances(): network index length (%d) is out of bounds for min/max instances (%d-%d)\n", networkIndexListLen, minCount, maxCount); return(1); } for (i=0; i (vnetconfig->numaddrs-1)) ) { logprintfl(EUCAERROR, "RunInstances(): network index (%d) out of bounds (0-%d)\n", networkIndexList[i], vnetconfig->numaddrs-1); return(1); } } // all checked out nidx=0; } retInsts = malloc(sizeof(ccInstance) * maxCount); if (!retInsts) { logprintfl(EUCAFATAL, "RunInstances(): out of memory!\n"); unlock_exit(1); } runCount=0; // get updated resource information done=0; for (i=0; i= maxCount) { strncpy(mac, macAddrs[i], 32); } sem_mywait(VNET); if (nidx == -1) { rc = vnetGenerateNetworkParams(vnetconfig, instId, vlan, -1, mac, pubip, privip); thenidx = -1; } else { rc = vnetGenerateNetworkParams(vnetconfig, instId, vlan, networkIndexList[nidx], mac, pubip, privip); thenidx=nidx; nidx++; } if (rc) { foundnet = 0; } else { foundnet = 1; } sem_mypost(VNET); if (thenidx != -1) { logprintfl(EUCADEBUG,"RunInstances(): assigning MAC/IP: %s/%s/%s/%d\n", mac, pubip, privip, networkIndexList[thenidx]); } else { logprintfl(EUCADEBUG,"RunInstances(): assigning MAC/IP: %s/%s/%s/%d\n", mac, pubip, privip, thenidx); } if (mac[0] == '\0' || !foundnet) { logprintfl(EUCAERROR,"RunInstances(): could not find/initialize any free network address, failing doRunInstances()\n"); } else { // "run" the instance memcpy (&ncvm, ccvm, sizeof(virtualMachine)); ncnet.vlan = vlan; if (thenidx >= 0) { ncnet.networkIndex = networkIndexList[thenidx]; } else { ncnet.networkIndex = -1; } snprintf(ncnet.privateMac, 24, "%s", mac); snprintf(ncnet.privateIp, 24, "%s", privip); snprintf(ncnet.publicIp, 24, "%s", pubip); sem_mywait(RESCACHE); resid = 0; sem_mywait(CONFIG); rc = schedule_instance(ccvm, targetNode, &resid); sem_mypost(CONFIG); res = &(resourceCache->resources[resid]); if (rc) { // could not find resource logprintfl(EUCAERROR, "RunInstances(): scheduler could not find resource to run the instance on\n"); // couldn't run this VM, remove networking information from system free_instanceNetwork(mac, vlan, 1, 1); } else { int pid, status, ret, rbytes; // try to run the instance on the chosen resource logprintfl(EUCADEBUG, "RunInstances(): scheduler decided to run instance '%s' on resource '%s', running count '%d'\n", instId, res->ncURL, res->running); outInst=NULL; pid = fork(); if (pid == 0) { time_t startRun; sem_mywait(RESCACHE); if (res->running > 0) { res->running++; } sem_mypost(RESCACHE); ret=0; 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); rc = 1; startRun = time(NULL); while(rc && ((time(NULL) - startRun) < config->wakeThresh)){ int clientpid; // call StartNetwork client rc = ncClientCall(ccMeta, OP_TIMEOUT_PERNODE, NCCALL, res->ncURL, "ncStartNetwork", NULL, 0, 0, vlan, NULL); 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); if (rc) { sleep(1); } } if (!rc) { ret = 0; } else { ret = 1; } sem_mywait(RESCACHE); if (res->running > 0) { res->running--; } sem_mypost(RESCACHE); exit(ret); } else { rc = 0; logprintfl(EUCADEBUG,"RunInstances(): call complete (pid/rc): %d/%d\n", pid, rc); } if (rc != 0) { // problem logprintfl(EUCAERROR, "RunInstances(): tried to run the VM, but runInstance() failed; marking resource '%s' as down\n", res->ncURL); res->state = RESDOWN; i--; // couldn't run this VM, remove networking information from system free_instanceNetwork(mac, vlan, 1, 1); } else { res->availMemory -= ccvm->mem; res->availDisk -= ccvm->disk; res->availCores -= ccvm->cores; 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); myInstance = &(retInsts[runCount]); bzero(myInstance, sizeof(ccInstance)); 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); // start up DHCP sem_mywait(CONFIG); config->kick_dhcp = 1; sem_mypost(CONFIG); // add the instance to the cache, and continue on add_instanceCache(myInstance->instanceId, myInstance); print_ccInstance("RunInstances(): ", myInstance); runCount++; } } sem_mypost(RESCACHE); } } *outInstsLen = runCount; *outInsts = retInsts; logprintfl(EUCADEBUG,"RunInstances(): done\n"); shawn(); if (error) { return(1); } return(0); } int doGetConsoleOutput(ncMetadata *meta, char *instId, char **outConsoleOutput) { int i, j, rc, numInsts, start, stop, done, ret, rbytes, timeout=0; ccInstance *myInstance; ncStub *ncs; char *consoleOutput; time_t op_start; ccResourceCache resourceCacheLocal; i = j = numInsts = 0; op_start = time(NULL); consoleOutput = NULL; myInstance = NULL; *outConsoleOutput = NULL; rc = initialize(); if (rc) { return(1); } logprintfl(EUCAINFO,"GetConsoleOutput(): called\n"); logprintfl(EUCADEBUG,"GetConsoleOutput(): params: userId=%s, instId=%s\n", SP(meta->userId), SP(instId)); sem_mywait(RESCACHE); memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache)); sem_mypost(RESCACHE); rc = find_instanceCacheId(instId, &myInstance); if (!rc) { // found the instance in the cache start = myInstance->ncHostIdx; stop = start+1; free(myInstance); } else { start = 0; stop = resourceCacheLocal.numResources; } done=0; for (j=start; juserId), instIdsLen); sem_mywait(RESCACHE); memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache)); sem_mypost(RESCACHE); for (i=0; incHostIdx; stop = start+1; free(myInstance); } else { start = 0; stop = resourceCacheLocal.numResources; } done=0; for (j=start; juserId : "UNSET"), instIdsLen, SP(instIdsLen ? instIds[0] : "UNSET")); sem_mywait(RESCACHE); memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache)); sem_mypost(RESCACHE); for (i=0; istate, "Pending") || !strcmp(myInstance->state, "Extant") || !strcmp(myInstance->state, "Unknown")) { start = myInstance->ncHostIdx; stop = start+1; } else { // instance is not in a terminatable state start = 0; stop = 0; (*outStatus)[i] = 0; } rc = free_instanceNetwork(myInstance->ccnet.privateMac, myInstance->ccnet.vlan, 1, 1); free(myInstance); } else { // instance is not in cache, try all resources start = 0; stop = 0; (*outStatus)[i] = 0; } done=0; for (j=start; j= 0) { // if this is the first process to create the config, init to 0 rc = ftruncate(shd, bytes); } else { shd = shm_open(bufname, O_CREAT | O_RDWR, 0644); } if (shd < 0) { fprintf(stderr, "cannot initialize shared memory segment\n"); sem_post(*lock); sem_close(*lock); return(1); } *buf = mmap(0, bytes, PROT_READ | PROT_WRITE, MAP_SHARED, shd, 0); } else if (mode == SHARED_FILE) { char *tmpstr, path[MAX_PATH]; struct stat mystat; int fd; tmpstr = getenv(EUCALYPTUS_ENV_VAR_NAME); if (!tmpstr) { snprintf(path, MAX_PATH, "/var/lib/eucalyptus/CC/%s", bufname); } else { snprintf(path, MAX_PATH, "%s/var/lib/eucalyptus/CC/%s", tmpstr, bufname); } fd = open(path, O_RDWR | O_CREAT, 0600); if (fd<0) { fprintf(stderr, "ERROR: cannot open/create '%s' to set up mmapped buffer\n", path); ret = 1; } else { mystat.st_size = 0; rc = fstat(fd, &mystat); // this is the check to make sure we're dealing with a valid prior config if (mystat.st_size != bytes) { rc = ftruncate(fd, bytes); } *buf = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (*buf == NULL) { fprintf(stderr, "ERROR: cannot mmap fd\n"); ret = 1; } close(fd); } } sem_post(*lock); return(ret); } int initialize(void) { int rc, ret; ret=0; rc = init_thread(); if (rc) { ret=1; logprintfl(EUCAERROR, "initialize(): cannot initialize thread\n"); } rc = init_localstate(); if (rc) { ret = 1; logprintfl(EUCAERROR, "initialize(): cannot initialize local state\n"); } rc = init_config(); if (rc) { ret=1; logprintfl(EUCAERROR, "initialize(): cannot initialize from configuration file\n"); } if (config->use_tunnels) { rc = vnetInitTunnels(vnetconfig); if (rc) { logprintfl(EUCAERROR, "initialize(): cannot initialize tunnels\n"); } } rc = init_pthreads(); if (rc) { logprintfl(EUCAERROR, "initialize(): cannot initialize background threads\n"); ret = 1; } if (!ret) { // initialization went well, this thread is now initialized init=1; } return(ret); } /* As of 1.6.2, the CC will start a background thread to poll its collection of nodes. This thread populates an in-memory cache of instance and resource information that can be accessed via the regular describeInstances and describeResources calls to the CC. The purpose of this separation is to allow for a more scalable framework where describe operations do not block on access to node controllers. */ void *monitor_thread(void *in) { int rc; ncMetadata ccMeta; ccMeta.correlationId = strdup("monitor"); ccMeta.userId = strdup("eucalyptus"); if (!ccMeta.correlationId || !ccMeta.userId) { logprintfl(EUCAFATAL, "monitor_thread(): out of memory!\n"); unlock_exit(1); } while(1) { // set up default signal handler for this child process (for SIGTERM) struct sigaction newsigact; newsigact.sa_handler = SIG_DFL; newsigact.sa_flags = 0; sigemptyset(&newsigact.sa_mask); sigprocmask(SIG_SETMASK, &newsigact.sa_mask, NULL); sigaction(SIGTERM, &newsigact, NULL); logprintfl(EUCADEBUG, "monitor_thread(): running\n"); rc = refresh_resources(&ccMeta, 60, 1); if (rc) { logprintfl(EUCAWARN, "monitor_thread(): call to refresh_resources() failed in monitor thread\n"); } rc = refresh_instances(&ccMeta, 60, 1); if (rc) { logprintfl(EUCAWARN, "monitor_thread(): call to refresh_instances() failed in monitor thread\n"); } sem_mywait(CONFIG); if (config->kick_dhcp) { rc = vnetKickDHCP(vnetconfig); if (rc) { logprintfl(EUCAERROR, "monitor_thread(): cannot start DHCP daemon\n"); } else { config->kick_dhcp = 0; } } sem_mypost(CONFIG); shawn(); logprintfl(EUCADEBUG, "monitor_thread(): done\n"); sleep(config->ncPollingFrequency); } return(NULL); } int init_pthreads() { // start any background threads if (!config_init) { return(1); } sem_mywait(CONFIG); if (config->threads[MONITOR] == 0 || check_process(config->threads[MONITOR], "httpd-cc.conf")) { int pid; pid = fork(); if (!pid) { // set up default signal handler for this child process (for SIGTERM) struct sigaction newsigact; newsigact.sa_handler = SIG_DFL; newsigact.sa_flags = 0; sigemptyset(&newsigact.sa_mask); sigprocmask(SIG_SETMASK, &newsigact.sa_mask, NULL); sigaction(SIGTERM, &newsigact, NULL); monitor_thread(NULL); exit(0); } else { config->threads[MONITOR] = pid; } } sem_mypost(CONFIG); return(0); } int init_localstate(void) { int rc, loglevel, ret; char *tmpstr=NULL, logFile[MAX_PATH], configFiles[2][MAX_PATH], home[MAX_PATH], vfile[MAX_PATH]; ret=0; if (local_init) { } else { // thread is not initialized, run first time local state setup bzero(logFile, MAX_PATH); bzero(home, MAX_PATH); bzero(configFiles[0], MAX_PATH); bzero(configFiles[1], MAX_PATH); tmpstr = getenv(EUCALYPTUS_ENV_VAR_NAME); if (!tmpstr) { snprintf(home, MAX_PATH, "/"); } else { snprintf(home, MAX_PATH, "%s", tmpstr); } snprintf(configFiles[1], MAX_PATH, EUCALYPTUS_CONF_LOCATION, home); snprintf(configFiles[0], MAX_PATH, EUCALYPTUS_CONF_OVERRIDE_LOCATION, home); snprintf(logFile, MAX_PATH, "%s/var/log/eucalyptus/cc.log", home); tmpstr = getConfString(configFiles, 2, "LOGLEVEL"); if (!tmpstr) { loglevel = EUCADEBUG; } else { if (!strcmp(tmpstr,"DEBUG")) {loglevel=EUCADEBUG;} else if (!strcmp(tmpstr,"INFO")) {loglevel=EUCAINFO;} else if (!strcmp(tmpstr,"WARN")) {loglevel=EUCAWARN;} else if (!strcmp(tmpstr,"ERROR")) {loglevel=EUCAERROR;} else if (!strcmp(tmpstr,"FATAL")) {loglevel=EUCAFATAL;} else {loglevel=EUCADEBUG;} } if (tmpstr) free(tmpstr); // set up logfile logfile(logFile, loglevel); local_init=1; } return(ret); } int init_thread(void) { int rc; logprintfl(EUCADEBUG, "init_thread(): init=%d %08X %08X %08X %08X\n", init, config, vnetconfig, instanceCache, resourceCache); if (thread_init) { // thread has already been initialized } else { // this thread has not been initialized, set up shared memory segments srand(time(NULL)); locks[INIT] = sem_open("/eucalyptusCCinitLock", O_CREAT, 0644, 1); sem_mywait(INIT); locks[NCCALL] = sem_open("/eucalyptusCCncCallLock", O_CREAT, 0644, 4); if (config == NULL) { rc = setup_shared_buffer((void **)&config, "/eucalyptusCCConfig", sizeof(ccConfig), &(locks[CONFIG]), "/eucalyptusCCConfigLock", SHARED_FILE); if (rc != 0) { fprintf(stderr, "init_thread(): Cannot set up shared memory region for ccConfig, exiting...\n"); sem_mypost(INIT); exit(1); } } if (instanceCache == NULL) { rc = setup_shared_buffer((void **)&instanceCache, "/eucalyptusCCInstanceCache", sizeof(ccInstanceCache), &(locks[INSTCACHE]), "/eucalyptusCCInstanceCacheLock", SHARED_FILE); if (rc != 0) { fprintf(stderr, "init_thread(): Cannot set up shared memory region for ccInstanceCache, exiting...\n"); sem_mypost(INIT); exit(1); } } if (resourceCache == NULL) { rc = setup_shared_buffer((void **)&resourceCache, "/eucalyptusCCResourceCache", sizeof(ccResourceCache), &(locks[RESCACHE]), "/eucalyptusCCResourceCacheLock", SHARED_FILE); if (rc != 0) { fprintf(stderr, "init_thread(): Cannot set up shared memory region for ccResourceCache, exiting...\n"); sem_mypost(INIT); exit(1); } } if (vnetconfig == NULL) { rc = setup_shared_buffer((void **)&vnetconfig, "/eucalyptusCCVNETConfig", sizeof(vnetConfig), &(locks[VNET]), "/eucalyptusCCVNETConfigLock", SHARED_FILE); if (rc != 0) { fprintf(stderr, "init_thread(): Cannot set up shared memory region for ccVNETConfig, exiting...\n"); sem_mypost(INIT); exit(1); } } sem_mypost(INIT); thread_init=1; } return(0); } int update_config(void) { char home[MAX_PATH], *tmpstr=NULL; ccResource *res=NULL; int rc, numHosts, ret; time_t configMtime; struct stat statbuf; int i; ret = 0; configMtime = 0; sem_mywait(CONFIG); for (i=0; i<2; i++) { // stat the config file, update modification time rc = stat(config->configFiles[i], &statbuf); if (!rc) { if (statbuf.st_mtime > configMtime) { configMtime = statbuf.st_mtime; } } } if (configMtime == 0) { logprintfl(EUCAERROR, "update_config(): could not stat config files (%s,%s)\n", config->configFiles[0], config->configFiles[1]); sem_mypost(CONFIG); return(1); } // check to see if the configfile has changed if (config->configMtime != configMtime) { // something has changed logprintfl(EUCAINFO, "update_config(): config file has been modified, refreshing node list\n"); res = NULL; rc = refreshNodes(config, &res, &numHosts); if (rc) { logprintfl(EUCAERROR, "update_config(): cannot read list of nodes, check your config file\n"); sem_mywait(RESCACHE); resourceCache->numResources = 0; config->schedState = 0; bzero(resourceCache->resources, sizeof(ccResource) * MAXNODES); sem_mypost(RESCACHE); ret = 1; } else { sem_mywait(RESCACHE); if (numHosts > MAXNODES) { 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); numHosts = MAXNODES; } resourceCache->numResources = numHosts; config->schedState = 0; memcpy(resourceCache->resources, res, sizeof(ccResource) * numHosts); sem_mypost(RESCACHE); } if (res) free(res); } config->configMtime = configMtime; sem_mypost(CONFIG); return(ret); } int init_config(void) { ccResource *res=NULL; char *tmpstr=NULL; int rc, numHosts, use_wssec, use_tunnels, schedPolicy, idleThresh, wakeThresh, ret, i; char configFiles[2][MAX_PATH], netPath[MAX_PATH], eucahome[MAX_PATH], policyFile[MAX_PATH], home[MAX_PATH]; time_t configMtime, instanceTimeout, ncPollingFrequency; struct stat statbuf; // read in base config information tmpstr = getenv(EUCALYPTUS_ENV_VAR_NAME); if (!tmpstr) { snprintf(home, MAX_PATH, "/"); } else { snprintf(home, MAX_PATH, "%s", tmpstr); } bzero(configFiles[0], MAX_PATH); bzero(configFiles[1], MAX_PATH); bzero(netPath, MAX_PATH); bzero(policyFile, MAX_PATH); snprintf(configFiles[1], MAX_PATH, EUCALYPTUS_CONF_LOCATION, home); snprintf(configFiles[0], MAX_PATH, EUCALYPTUS_CONF_OVERRIDE_LOCATION, home); snprintf(netPath, MAX_PATH, CC_NET_PATH_DEFAULT, home); snprintf(policyFile, MAX_PATH, "%s/var/lib/eucalyptus/keys/nc-client-policy.xml", home); snprintf(eucahome, MAX_PATH, "%s/", home); if (config_init && config->initialized) { // this means that this thread has already been initialized ret = 0; return(ret); } if (config->initialized) { // some other thread has already initialized the configuration logprintfl(EUCAINFO, "init_config(): another thread has already set up config, skipping\n"); rc = restoreNetworkState(); if (rc) { // failed to restore network state, continue logprintfl(EUCAWARN, "init_config(): restoreNetworkState returned false (may be already restored)\n"); } config_init = 1; return(0); } logprintfl(EUCADEBUG,"init_config(): initializing CC configuration\n"); // DHCP configuration section { char *daemon=NULL, *dhcpuser=NULL, *numaddrs=NULL, *pubmode=NULL, *pubmacmap=NULL, *pubips=NULL, *pubInterface=NULL, *privInterface=NULL, *pubSubnet=NULL, *pubSubnetMask=NULL, *pubBroadcastAddress=NULL, *pubRouter=NULL, *pubDNS=NULL, *localIp=NULL, *cloudIp=NULL; uint32_t *ips, *nms; int initFail=0, len; // DHCP Daemon Configuration Params daemon = getConfString(configFiles, 2, "VNET_DHCPDAEMON"); if (!daemon) { logprintfl(EUCAWARN,"init_config(): no VNET_DHCPDAEMON defined in config, using default\n"); } dhcpuser = getConfString(configFiles, 2, "VNET_DHCPUSER"); if (!dhcpuser) { dhcpuser = strdup("root"); if (!dhcpuser) { logprintfl(EUCAFATAL,"init_config(): Out of memory\n"); unlock_exit(1); } } pubmode = getConfString(configFiles, 2, "VNET_MODE"); if (!pubmode) { logprintfl(EUCAWARN,"init_config(): VNET_MODE is not defined, defaulting to 'SYSTEM'\n"); pubmode = strdup("SYSTEM"); if (!pubmode) { logprintfl(EUCAFATAL,"init_config(): Out of memory\n"); unlock_exit(1); } } { int usednew=0; pubInterface = getConfString(configFiles, 2, "VNET_PUBINTERFACE"); if (!pubInterface) { logprintfl(EUCAWARN,"init_config(): VNET_PUBINTERFACE is not defined, defaulting to 'eth0'\n"); pubInterface = strdup("eth0"); if (!pubInterface) { logprintfl(EUCAFATAL, "init_config(): out of memory!\n"); unlock_exit(1); } } else { usednew=1; } privInterface = NULL; privInterface = getConfString(configFiles, 2, "VNET_PRIVINTERFACE"); if (!privInterface) { logprintfl(EUCAWARN,"init_config(): VNET_PRIVINTERFACE is not defined, defaulting to 'eth0'\n"); privInterface = strdup("eth0"); if (!privInterface) { logprintfl(EUCAFATAL, "init_config(): out of memory!\n"); unlock_exit(1); } usednew = 0; } if (!usednew) { tmpstr = NULL; tmpstr = getConfString(configFiles, 2, "VNET_INTERFACE"); if (tmpstr) { 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); if (pubInterface) free(pubInterface); pubInterface = strdup(tmpstr); if (!pubInterface) { logprintfl(EUCAFATAL, "init_config(): out of memory!\n"); unlock_exit(1); } if (privInterface) free(privInterface); privInterface = strdup(tmpstr); if (!privInterface) { logprintfl(EUCAFATAL, "init_config(): out of memory!\n"); unlock_exit(1); } } if (tmpstr) free(tmpstr); } } if (pubmode && !strcmp(pubmode, "STATIC")) { pubSubnet = getConfString(configFiles, 2, "VNET_SUBNET"); pubSubnetMask = getConfString(configFiles, 2, "VNET_NETMASK"); pubBroadcastAddress = getConfString(configFiles, 2, "VNET_BROADCAST"); pubRouter = getConfString(configFiles, 2, "VNET_ROUTER"); pubDNS = getConfString(configFiles, 2, "VNET_DNS"); pubmacmap = getConfString(configFiles, 2, "VNET_MACMAP"); if (!pubSubnet || !pubSubnetMask || !pubBroadcastAddress || !pubRouter || !pubDNS || !pubmacmap) { 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"); initFail = 1; } } else if (pubmode && (!strcmp(pubmode, "MANAGED") || !strcmp(pubmode, "MANAGED-NOVLAN"))) { numaddrs = getConfString(configFiles, 2, "VNET_ADDRSPERNET"); pubSubnet = getConfString(configFiles, 2, "VNET_SUBNET"); pubSubnetMask = getConfString(configFiles, 2, "VNET_NETMASK"); pubDNS = getConfString(configFiles, 2, "VNET_DNS"); pubips = getConfString(configFiles, 2, "VNET_PUBLICIPS"); localIp = getConfString(configFiles, 2, "VNET_LOCALIP"); if (!localIp) { logprintfl(EUCAWARN, "init_config(): VNET_LOCALIP not defined, will attempt to auto-discover (consider setting this explicitly if tunnelling does not function properly.)\n"); } cloudIp = getConfString(configFiles, 2, "VNET_CLOUDIP"); if (!pubSubnet || !pubSubnetMask || !pubDNS || !numaddrs) { 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"); initFail = 1; } } if (initFail) { logprintfl(EUCAFATAL, "init_config(): bad network parameters, must fix before system will work\n"); if (cloudIp) free(cloudIp); if (pubSubnet) free(pubSubnet); if (pubSubnetMask) free(pubSubnetMask); if (pubBroadcastAddress) free(pubBroadcastAddress); if (pubRouter) free(pubRouter); if (pubDNS) free(pubDNS); if (pubmacmap) free(pubmacmap); if (numaddrs) free(numaddrs); if (pubips) free(pubips); if (localIp) free(localIp); if (pubInterface) free(pubInterface); if (privInterface) free(privInterface); if (dhcpuser) free(dhcpuser); if (daemon) free(daemon); if (pubmode) free(pubmode); return(1); } sem_mywait(VNET); vnetInit(vnetconfig, pubmode, eucahome, netPath, CLC, pubInterface, privInterface, numaddrs, pubSubnet, pubSubnetMask, pubBroadcastAddress, pubDNS, pubRouter, daemon, dhcpuser, NULL, localIp, cloudIp); if (cloudIp) free(cloudIp); if (pubSubnet) free(pubSubnet); if (pubSubnetMask) free(pubSubnetMask); if (pubBroadcastAddress) free(pubBroadcastAddress); if (pubDNS) free(pubDNS); if (pubRouter) free(pubRouter); if (numaddrs) free(numaddrs); if (pubmode) free(pubmode); if (dhcpuser) free(dhcpuser); if (daemon) free(daemon); if (privInterface) free(privInterface); if (pubInterface) free(pubInterface); vnetAddDev(vnetconfig, vnetconfig->privInterface); if (pubmacmap) { char *mac=NULL, *ip=NULL, *ptra=NULL, *toka=NULL, *ptrb=NULL; toka = strtok_r(pubmacmap, " ", &ptra); while(toka) { mac = ip = NULL; mac = strtok_r(toka, "=", &ptrb); ip = strtok_r(NULL, "=", &ptrb); if (mac && ip) { vnetAddHost(vnetconfig, mac, ip, 0, -1); } toka = strtok_r(NULL, " ", &ptra); } vnetKickDHCP(vnetconfig); free(pubmacmap); } else if (pubips) { char *ip, *ptra, *toka; toka = strtok_r(pubips, " ", &ptra); while(toka) { ip = toka; if (ip) { rc = vnetAddPublicIP(vnetconfig, ip); if (rc) { logprintfl(EUCAERROR, "init_config(): could not add public IP '%s'\n", ip); } } toka = strtok_r(NULL, " ", &ptra); } // detect and populate ips if (vnetCountLocalIP(vnetconfig) <= 0) { ips = nms = NULL; rc = getdevinfo("all", &ips, &nms, &len); if (!rc) { for (i=0; ieucahome, eucahome, MAX_PATH); strncpy(config->policyFile, policyFile, MAX_PATH); config->use_wssec = use_wssec; config->use_tunnels = use_tunnels; config->schedPolicy = schedPolicy; config->idleThresh = idleThresh; config->wakeThresh = wakeThresh; // config->configMtime = configMtime; config->instanceTimeout = instanceTimeout; config->ncPollingFrequency = ncPollingFrequency; config->initialized = 1; snprintf(config->configFiles[0], MAX_PATH, "%s", configFiles[0]); snprintf(config->configFiles[1], MAX_PATH, "%s", configFiles[1]); 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); sem_mypost(CONFIG); res = NULL; rc = refreshNodes(config, &res, &numHosts); if (rc) { logprintfl(EUCAERROR, "init_config(): cannot read list of nodes, check your config file\n"); return(1); } // update resourceCache sem_mywait(RESCACHE); resourceCache->numResources = numHosts; if (numHosts) { memcpy(resourceCache->resources, res, sizeof(ccResource) * numHosts); } if (res) free(res); resourceCache->lastResourceUpdate = 0; sem_mypost(RESCACHE); config_init=1; logprintfl(EUCADEBUG,"init_config(): done\n"); return(0); } int maintainNetworkState() { int rc, i, ret=0; time_t startTime, startTimeA; if (!strcmp(vnetconfig->mode, "MANAGED") || !strcmp(vnetconfig->mode, "MANAGED-NOVLAN")) { sem_mywait(VNET); rc = vnetSetupTunnels(vnetconfig); if (rc) { logprintfl(EUCAERROR, "maintainNetworkState(): failed to setup tunnels during maintainNetworkState()\n"); ret = 1; } for (i=2; inetworks[i].active) { char brname[32]; if (!strcmp(vnetconfig->mode, "MANAGED")) { snprintf(brname, 32, "eucabr%d", i); } else { snprintf(brname, 32, "%s", vnetconfig->privInterface); } startTime=time(NULL); rc = vnetAttachTunnels(vnetconfig, i, brname); if (rc) { logprintfl(EUCADEBUG, "maintainNetworkState(): failed to attach tunnels for vlan %d during maintainNetworkState()\n", i); ret = 1; } } } sem_mypost(VNET); } return(ret); } int restoreNetworkState() { int rc, ret=0, i; char cmd[MAX_PATH]; logprintfl(EUCADEBUG, "restoreNetworkState(): restoring network state\n"); sem_mywait(VNET); // restore iptables state logprintfl(EUCADEBUG, "restoreNetworkState(): restarting iptables\n"); rc = vnetRestoreTablesFromMemory(vnetconfig); if (rc) { logprintfl(EUCAERROR, "restoreNetworkState(): cannot restore iptables state\n"); ret = 1; } // restore ip addresses logprintfl(EUCADEBUG, "restoreNetworkState(): restarting ips\n"); if (!strcmp(vnetconfig->mode, "MANAGED") || !strcmp(vnetconfig->mode, "MANAGED-NOVLAN")) { 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); logprintfl(EUCADEBUG,"restoreNetworkState(): running cmd %s\n", cmd); rc = system(cmd); if (rc) { logprintfl(EUCAWARN, "restoreNetworkState(): cannot add ip 169.254.169.254\n"); } } for (i=1; ipublicips[i].allocated) { char *tmp; tmp = hex2dot(vnetconfig->publicips[i].ip); snprintf(cmd, MAX_PATH, "%s/usr/lib/eucalyptus/euca_rootwrap ip addr add %s/32 dev %s", config->eucahome, tmp, vnetconfig->pubInterface); logprintfl(EUCADEBUG,"restoreNetworkState(): running cmd %s\n", cmd); rc = system(cmd); if (rc) { logprintfl(EUCAWARN, "restoreNetworkState(): cannot add ip %s\n", tmp); } free(tmp); } } // re-create all active networks logprintfl(EUCADEBUG, "restoreNetworkState(): restarting networks\n"); for (i=2; inetworks[i].active) { char *brname=NULL; logprintfl(EUCADEBUG, "restoreNetworkState(): found active network: %d\n", i); rc = vnetStartNetwork(vnetconfig, i, vnetconfig->users[i].userName, vnetconfig->users[i].netName, &brname); if (rc) { logprintfl(EUCADEBUG, "restoreNetworkState(): failed to reactivate network: %d", i); } if (brname) free(brname); } } // get DHCPD back up and running logprintfl(EUCADEBUG, "restoreNetworkState(): restarting DHCPD\n"); rc = vnetKickDHCP(vnetconfig); if (rc) { logprintfl(EUCAERROR, "restoreNetworkState(): cannot start DHCP daemon, please check your network settings\n"); ret = 1; } sem_mypost(VNET); logprintfl(EUCADEBUG, "restoreNetworkState(): done restoring network state\n"); return(ret); } int refreshNodes(ccConfig *config, ccResource **res, int *numHosts) { int rc, i; char *tmpstr, *ipbuf; char ncservice[512]; int ncport; char **hosts; *numHosts = 0; *res = NULL; tmpstr = getConfString(config->configFiles, 2, CONFIG_NC_SERVICE); if (!tmpstr) { // error logprintfl(EUCAFATAL,"refreshNodes(): parsing config files (%s,%s) for NC_SERVICE\n", config->configFiles[1], config->configFiles[0]); return(1); } else { if(tmpstr) { snprintf(ncservice, 512, "%s", tmpstr); } } if (tmpstr) free(tmpstr); tmpstr = getConfString(config->configFiles, 2, CONFIG_NC_PORT); if (!tmpstr) { // error logprintfl(EUCAFATAL,"refreshNodes(): parsing config files (%s,%s) for NC_PORT\n", config->configFiles[1], config->configFiles[0]); return(1); } else { if(tmpstr) ncport = atoi(tmpstr); } if (tmpstr) free(tmpstr); tmpstr = getConfString(config->configFiles, 2, CONFIG_NODES); if (!tmpstr) { // error logprintfl(EUCAWARN,"refreshNodes(): NODES parameter is missing from config files(%s,%s)\n", config->configFiles[1], config->configFiles[0]); return(0); } else { hosts = from_var_to_char_list(tmpstr); if (hosts == NULL) { logprintfl(EUCAWARN,"refreshNodes(): NODES list is empty in config files(%s,%s)\n", config->configFiles[1], config->configFiles[0]); if (tmpstr) free(tmpstr); return(0); } *numHosts = 0; i = 0; while(hosts[i] != NULL) { (*numHosts)++; *res = realloc(*res, sizeof(ccResource) * *numHosts); bzero(&((*res)[*numHosts-1]), sizeof(ccResource)); snprintf((*res)[*numHosts-1].hostname, 128, "%s", hosts[i]); ipbuf = host2ip(hosts[i]); if (ipbuf) { snprintf((*res)[*numHosts-1].ip, 24, "%s", ipbuf); } if (ipbuf) free(ipbuf); (*res)[*numHosts-1].ncPort = ncport; snprintf((*res)[*numHosts-1].ncService, 128, "%s", ncservice); snprintf((*res)[*numHosts-1].ncURL, 128, "http://%s:%d/%s", hosts[i], ncport, ncservice); (*res)[*numHosts-1].state = RESDOWN; (*res)[*numHosts-1].lastState = RESDOWN; free(hosts[i]); i++; } } if (hosts) free(hosts); if (tmpstr) free(tmpstr); return(0); } void shawn() { int p=1, status, rc; // clean up any orphaned child processes while(p > 0) { p = waitpid(-1, &status, WNOHANG); } rc = maintainNetworkState(); if (rc) { logprintfl(EUCAERROR, "shawn(): network state maintainance failed\n"); } if (instanceCache) msync(instanceCache, sizeof(ccInstanceCache), MS_ASYNC); if (resourceCache) msync(resourceCache, sizeof(ccResourceCache), MS_ASYNC); if (config) msync(config, sizeof(ccConfig), MS_ASYNC); if (vnetconfig) msync(vnetconfig, sizeof(vnetConfig), MS_ASYNC); } int timeread(int fd, void *buf, size_t bytes, int timeout) { int rc; fd_set rfds; struct timeval tv; if (timeout <= 0) timeout = 1; FD_ZERO(&rfds); FD_SET(fd, &rfds); tv.tv_sec = timeout; tv.tv_usec = 0; rc = select(fd+1, &rfds, NULL, NULL, &tv); if (rc <= 0) { // timeout logprintfl(EUCAERROR, "timeread(): select() timed out for read: timeout=%d\n", timeout); return(-1); } rc = read(fd, buf, bytes); return(rc); } 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) { if (out != NULL) { if (ncURL) strncpy(out->ncURL, ncURL, 128); if (ncService) strncpy(out->ncService, ncService, 128); if (hostname) strncpy(out->hostname, hostname, 128); if (mac) strncpy(out->mac, mac, 24); if (ip) strncpy(out->ip, ip, 24); out->ncPort = ncPort; out->maxMemory = maxMemory; out->availMemory = availMemory; out->maxDisk = maxDisk; out->availDisk = availDisk; out->maxCores = maxCores; out->availCores = availCores; out->state = state; out->lastState = laststate; out->stateChange = stateChange; out->idleStart = idleStart; } return(0); } int free_instanceNetwork(char *mac, int vlan, int force, int dolock) { int inuse, i; unsigned char hexmac[6]; mac2hex(mac, hexmac); if (!maczero(hexmac)) { return(0); } if (dolock) { sem_mywait(INSTCACHE); } inuse=0; if (!force) { // check to make sure the mac isn't in use elsewhere for (i=0; iinstances[i].ccnet.privateMac, mac) && strcmp(instanceCache->instances[i].state, "Teardown")) { inuse++; } } } if (dolock) { sem_mypost(INSTCACHE); } if (!inuse) { // remove private network info from system sem_mywait(VNET); vnetDisableHost(vnetconfig, mac, NULL, 0); if (!strcmp(vnetconfig->mode, "MANAGED") || !strcmp(vnetconfig->mode, "MANAGED-NOVLAN")) { vnetDelHost(vnetconfig, mac, NULL, vlan); } sem_mypost(VNET); } return(0); } 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) { if (out != NULL) { bzero(out, sizeof(ccInstance)); if (id) strncpy(out->instanceId, id, 16); if (amiId) strncpy(out->amiId, amiId, 16); if (kernelId) strncpy(out->kernelId, kernelId, 16); if (ramdiskId) strncpy(out->ramdiskId, ramdiskId, 16); if (amiURL) strncpy(out->amiURL, amiURL, 512); if (kernelURL) strncpy(out->kernelURL, kernelURL, 512); if (ramdiskURL) strncpy(out->ramdiskURL, ramdiskURL, 512); if (state) strncpy(out->state, state, 16); if (ownerId) strncpy(out->ownerId, ownerId, 16); if (reservationId) strncpy(out->reservationId, reservationId, 16); if (keyName) strncpy(out->keyName, keyName, 1024); out->ts = ts; out->ncHostIdx = ncHostIdx; if (serviceTag) strncpy(out->serviceTag, serviceTag, 64); if (userData) strncpy(out->userData, userData, 4096); if (launchIndex) strncpy(out->launchIndex, launchIndex, 64); if (groupNames) { int i; for (i=0; i<64; i++) { if (groupNames[i]) { strncpy(out->groupNames[i], groupNames[i], 32); } } } if (volumes) { memcpy(out->volumes, volumes, sizeof(ncVolume) * EUCA_MAX_VOLUMES); } out->volumesSize = volumesSize; // if (networkIndex) out->networkIndex = networkIndex; if (ccnet) allocate_netConfig(&(out->ccnet), ccnet->privateMac, ccnet->privateIp, ccnet->publicIp, ccnet->vlan, ccnet->networkIndex); if (ccvm) allocate_virtualMachine(&(out->ccvm), ccvm); } return(0); } int pubIpCmp(ccInstance *inst, void *ip) { if (!ip || !inst) { return(1); } if (!strcmp((char *)ip, inst->ccnet.publicIp)) { return(0); } return(1); } int privIpCmp(ccInstance *inst, void *ip) { if (!ip || !inst) { return(1); } if (!strcmp((char *)ip, inst->ccnet.privateIp)) { return(0); } return(1); } int privIpSet(ccInstance *inst, void *ip) { if (!ip || !inst) { return(1); } logprintfl(EUCADEBUG, "privIpSet(): set: %s/%s\n", inst->ccnet.privateIp, (char *)ip); snprintf(inst->ccnet.privateIp, 24, "%s", (char *)ip); return(0); } int pubIpSet(ccInstance *inst, void *ip) { if (!ip || !inst) { return(1); } logprintfl(EUCADEBUG, "pubIpSet(): set: %s/%s\n", inst->ccnet.publicIp, (char *)ip); snprintf(inst->ccnet.publicIp, 24, "%s", (char *)ip); return(0); } int map_instanceCache(int (*match)(ccInstance *, void *), void *matchParam, int (*operate)(ccInstance *, void *), void *operateParam) { int i, ret=0; sem_mywait(INSTCACHE); for (i=0; iinstances[i]), matchParam)) { if (operate(&(instanceCache->instances[i]), operateParam)) { logprintfl(EUCAWARN, "map_instanceCache(): failed to operate at index %d\n", i); ret++; } } } sem_mypost(INSTCACHE); return(ret); } void print_instanceCache(void) { int i; sem_mywait(INSTCACHE); for (i=0; icacheState[i] == INSTVALID ) { 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); } } sem_mypost(INSTCACHE); } void print_ccInstance(char *tag, ccInstance *in) { char *volbuf, *groupbuf; int i; volbuf = malloc(sizeof(ncVolume)*EUCA_MAX_VOLUMES*2); bzero(volbuf, sizeof(ncVolume)*EUCA_MAX_VOLUMES*2); groupbuf = malloc(64*32*2); bzero(groupbuf, 64*32*2); for (i=0; i<64; i++) { if (in->groupNames[i][0] != '\0') { strncat(groupbuf, in->groupNames[i], 32); strncat(groupbuf, " ", 1); } } for (i=0; ivolumes[i].volumeId[0] != '\0') { strncat(volbuf, in->volumes[i].volumeId, CHAR_BUFFER_SIZE); strncat(volbuf, ",", 1); strncat(volbuf, in->volumes[i].remoteDev, CHAR_BUFFER_SIZE); strncat(volbuf, ",", 1); strncat(volbuf, in->volumes[i].localDev, CHAR_BUFFER_SIZE); strncat(volbuf, ",", 1); strncat(volbuf, in->volumes[i].stateName, CHAR_BUFFER_SIZE); strncat(volbuf, " ", 1); } } 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); free(volbuf); free(groupbuf); } void invalidate_instanceCache(void) { int i; sem_mywait(INSTCACHE); for (i=0; iinstances[i].state, "Teardown") ) { free_instanceNetwork(instanceCache->instances[i].ccnet.privateMac, instanceCache->instances[i].ccnet.vlan, 0, 0); } if ( (instanceCache->cacheState[i] == INSTVALID) && ((time(NULL) - instanceCache->lastseen[i]) > config->instanceTimeout)) { logprintfl(EUCADEBUG, "invalidate_instanceCache(): invalidating instance '%s' (last seen %d seconds ago)\n", instanceCache->instances[i].instanceId, (time(NULL) - instanceCache->lastseen[i])); bzero(&(instanceCache->instances[i]), sizeof(ccInstance)); instanceCache->lastseen[i] = 0; instanceCache->cacheState[i] = INSTINVALID; instanceCache->numInsts--; } } sem_mypost(INSTCACHE); } int refresh_instanceCache(char *instanceId, ccInstance *in){ int i, done, rc; if (!instanceId || !in) { return(1); } sem_mywait(INSTCACHE); done=0; for (i=0; iinstances[i].instanceId, instanceId)) { // in cache memcpy(&(instanceCache->instances[i]), in, sizeof(ccInstance)); instanceCache->lastseen[i] = time(NULL); sem_mypost(INSTCACHE); return(0); } } sem_mypost(INSTCACHE); add_instanceCache(instanceId, in); return(0); } int add_instanceCache(char *instanceId, ccInstance *in){ int i, done, firstNull=0; if (!instanceId || !in) { return(1); } sem_mywait(INSTCACHE); done=0; for (i=0; icacheState[i] == INSTVALID ) && (!strcmp(instanceCache->instances[i].instanceId, instanceId))) { // already in cache logprintfl(EUCADEBUG, "add_instanceCache(): '%s/%s/%s' already in cache\n", instanceId, in->ccnet.publicIp, in->ccnet.privateIp); instanceCache->lastseen[i] = time(NULL); sem_mypost(INSTCACHE); return(0); } else if ( instanceCache->cacheState[i] == INSTINVALID ) { firstNull = i; done++; } } logprintfl(EUCADEBUG, "add_instanceCache(): adding '%s/%s/%s/%d' to cache\n", instanceId, in->ccnet.publicIp, in->ccnet.privateIp, in->volumesSize); 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); instanceCache->numInsts++; instanceCache->lastseen[firstNull] = time(NULL); instanceCache->cacheState[firstNull] = INSTVALID; sem_mypost(INSTCACHE); return(0); } int del_instanceCacheId(char *instanceId) { int i; sem_mywait(INSTCACHE); for (i=0; icacheState[i] == INSTVALID) && (!strcmp(instanceCache->instances[i].instanceId, instanceId))) { // del from cache bzero(&(instanceCache->instances[i]), sizeof(ccInstance)); instanceCache->lastseen[i] = 0; instanceCache->cacheState[i] = INSTINVALID; instanceCache->numInsts--; sem_mypost(INSTCACHE); return(0); } } sem_mypost(INSTCACHE); return(0); } int find_instanceCacheId(char *instanceId, ccInstance **out) { int i, done; if (!instanceId || !out) { return(1); } sem_mywait(INSTCACHE); *out = NULL; done=0; for (i=0; iinstances[i].instanceId, instanceId)) { // found it *out = malloc(sizeof(ccInstance)); if (!*out) { logprintfl(EUCAFATAL, "find_instanceCacheId(): out of memory!\n"); unlock_exit(1); } 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); 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); done++; } } sem_mypost(INSTCACHE); if (done) { return(0); } return(1); } int find_instanceCacheIP(char *ip, ccInstance **out) { int i, done; if (!ip || !out) { return(1); } sem_mywait(INSTCACHE); *out = NULL; done=0; for (i=0; iinstances[i].ccnet.publicIp[0] != '\0' || instanceCache->instances[i].ccnet.privateIp[0] != '\0')) { if (!strcmp(instanceCache->instances[i].ccnet.publicIp, ip) || !strcmp(instanceCache->instances[i].ccnet.privateIp, ip)) { // found it *out = malloc(sizeof(ccInstance)); if (!*out) { logprintfl(EUCAFATAL, "find_instanceCacheIP(): out of memory!\n"); unlock_exit(1); } 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); done++; } } } sem_mypost(INSTCACHE); if (done) { return(0); } return(1); } void print_resourceCache(void) { int i; sem_mywait(RESCACHE); for (i=0; icacheState[i] == RESVALID) { 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); } } sem_mypost(RESCACHE); } void invalidate_resourceCache(void) { int i; sem_mywait(RESCACHE); bzero(resourceCache->cacheState, sizeof(int)*MAXNODES); resourceCache->numResources = 0; resourceCache->resourceCacheUpdate = 0; sem_mypost(RESCACHE); } int refresh_resourceCache(char *host, ccResource *in){ int i, done, rc; if (!host || !in) { return(1); } sem_mywait(RESCACHE); done=0; for (i=0; icacheState[i] == RESVALID) { if (!strcmp(resourceCache->resources[i].hostname, host)) { // in cache memcpy(&(resourceCache->resources[i]), in, sizeof(ccResource)); sem_mypost(RESCACHE); return(0); } } } sem_mypost(RESCACHE); add_resourceCache(host, in); return(0); } int add_resourceCache(char *host, ccResource *in){ int i, done, firstNull=0; if (!host || !in) { return(1); } sem_mywait(RESCACHE); done=0; for (i=0; icacheState[i] == RESVALID) { if (!strcmp(resourceCache->resources[i].hostname, host)) { // already in cache sem_mypost(RESCACHE); return(0); } } else { firstNull = i; done++; } } resourceCache->cacheState[firstNull] = RESVALID; 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); resourceCache->numResources++; sem_mypost(RESCACHE); return(0); } int del_resourceCacheId(char *host) { int i; sem_mywait(RESCACHE); for (i=0; icacheState[i] == RESVALID) { if (!strcmp(resourceCache->resources[i].hostname, host)) { // del from cache bzero(&(resourceCache->resources[i]), sizeof(ccResource)); resourceCache->cacheState[i] = RESINVALID; resourceCache->numResources--; sem_mypost(RESCACHE); return(0); } } } sem_mypost(RESCACHE); return(0); } int find_resourceCacheId(char *host, ccResource **out) { int i, done; if (!host || !out) { return(1); } sem_mywait(RESCACHE); *out = NULL; done=0; for (i=0; icacheState[i] == RESVALID) { if (!strcmp(resourceCache->resources[i].hostname, host)) { // found it *out = malloc(sizeof(ccResource)); if (!*out) { logprintfl(EUCAFATAL, "find_resourceCacheId(): out of memory!\n"); unlock_exit(1); } 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); done++; } } } sem_mypost(RESCACHE); if (done) { return(0); } return(1); } void unlock_exit(int code) { int i; logprintfl(EUCADEBUG, "unlock_exit(): params: code=%d\n", code); for (i=0; i