//! //! Handles the client describe instance request. //! //! @param[in] pStub a pointer to the node controller (NC) stub structure //! @param[in] pMeta a pointer to the node controller (NC) metadata structure //! @param[in] instIds a pointer the list of instance identifiers to retrieve data for //! @param[in] instIdsLen the number of instance identifiers in the instIds list //! @param[out] outInsts a pointer the list of instances for which we have data //! @param[out] outInstsLen the number of instances in the outInsts list. //! //! @return EUCA_OK on success or EUCA_ERROR on failure. //! int ncDescribeInstancesStub(ncStub * pStub, ncMetadata * pMeta, char **instIds, int instIdsLen, ncInstance *** outInsts, int *outInstsLen) { int i = 0; int numinsts = 0; ncInstance *newinst = NULL; LOGDEBUG("fakeNC: describeInstances(): params: instIdsLen=%d\n", instIdsLen); if (instIdsLen < 0) { LOGERROR("fakeNC: describeInstances(): bad input params\n"); return (EUCA_ERROR); } loadNcStuff(); // *outInstsLen = myconfig->instanceidx+1; *outInsts = EUCA_ZALLOC(MAX_FAKE_INSTANCES, sizeof(ncInstance *)); for (i = 0; i < MAX_FAKE_INSTANCES; i++) { if (strlen(myconfig->global_instances[i].instanceId)) { newinst = EUCA_ZALLOC(1, sizeof(ncInstance)); if (!strcmp(myconfig->global_instances[i].stateName, "Pending")) { snprintf(myconfig->global_instances[i].stateName, 8, "Extant"); } memcpy(newinst, &(myconfig->global_instances[i]), sizeof(ncInstance)); (*outInsts)[numinsts] = newinst; LOGDEBUG("fakeNC: describeInstances(): idx=%d numinsts=%d instanceId=%s stateName=%s\n", i, numinsts, newinst->instanceId, newinst->stateName); numinsts++; } } *outInstsLen = numinsts; saveNcStuff(); return (EUCA_OK); }
//! //! Handles the reboot request of an instance. //! //! @param[in] nc a pointer to the NC state structure to initialize //! @param[in] pMeta a pointer to the node controller (NC) metadata structure //! @param[in] instanceId the instance identifier string (i-XXXXXXXX) //! //! @return EUCA_OK on success or proper error code. Known error code returned include: //! EUCA_ERROR, EUCA_NOT_FOUND_ERROR, and EUCA_FATAL_ERROR. //! static int doRebootInstance(struct nc_state_t *nc, ncMetadata * pMeta, char *instanceId) { pthread_t tcb = { 0 }; ncInstance *instance = NULL; rebooting_thread_params *params = NULL; sem_p(inst_sem); { instance = find_instance(&global_instances, instanceId); } sem_v(inst_sem); if (instance == NULL) { LOGERROR("[%s] cannot find instance\n", instanceId); return (EUCA_NOT_FOUND_ERROR); } params = EUCA_ZALLOC(1, sizeof(rebooting_thread_params)); memcpy(&(params->instance), instance, sizeof(ncInstance)); memcpy(&(params->nc), nc, sizeof(struct nc_state_t)); // since shutdown/restart may take a while, we do them in a thread if (pthread_create(&tcb, NULL, rebooting_thread, params)) { LOGERROR("[%s] failed to spawn a reboot thread\n", instanceId); return (EUCA_FATAL_ERROR); } set_corrid_pthread(get_corrid() != NULL ? get_corrid()->correlation_id : NULL, tcb); if (pthread_detach(tcb)) { LOGERROR("[%s] failed to detach the rebooting thread\n", instanceId); return (EUCA_FATAL_ERROR); } return (EUCA_OK); }
//! //! Initialize the network driver. //! //! @param[in] pConfig a pointer to our application configuration //! //! @return 0 on success or 1 if any failure occured. //! //! @see //! //! @pre //! - The core application configuration must be completed prior calling //! - The driver should not be already initialized (if its the case, a no-op will occur) //! - The pConfig parameter must not be NULL //! //! @post //! On success the driver is properly configured. On failure, the state of //! the driver is non-deterministic. If the driver was previously initialized, //! this will result into a no-op. //! //! @note //! static int network_driver_init(eucanetdConfig * pConfig) { int rc = 0; LOGINFO("Initializing '%s' network driver.\n", DRIVER_NAME()); // Make sure our given pointer is valid if (!pConfig) { LOGERROR("Failure to initialize '%s' networking mode. Invalid configuration parameter provided.\n", DRIVER_NAME()); return (1); } // Are we already initialized? if (IS_INITIALIZED()) { LOGERROR("Networking '%s' mode already initialized. Skipping!\n", DRIVER_NAME()); return (0); } // if (PEER_IS_NC(eucanetdPeer)) { if ((pMidoConfig = EUCA_ZALLOC(1, sizeof(mido_config))) == NULL) { LOGERROR("Failed to initialize '%s' networking mode. Out of memory!\n", DRIVER_NAME()); return (1); } rc = initialize_mido(pMidoConfig, pConfig->eucahome, pConfig->midosetupcore, pConfig->midoeucanetdhost, pConfig->midogwhost, pConfig->midogwip, pConfig->midogwiface, pConfig->midopubnw, pConfig->midopubgwip, "169.254.0.0", "17"); if (rc) { LOGERROR("could not initialize mido: please ensure that all required config options for MIDOVPC mode are set in eucalyptus.conf\n"); return (1); } // } // We are now initialize gInitialized = TRUE; return (0); }
//! //! Allocate and initialize a resource structure with given information. Resource is //! used to return information about resources //! //! @param[in] sNodeStatus the current node status string //! @param[in] migrationCapable flag indicating whether node can participate in live migration //! @param[in] sIQN //! @param[in] memorySizeMax the maximum amount of memory available on this node //! @param[in] memorySizeAvailable the current amount of memory available on this node //! @param[in] diskSizeMax the maximum amount of disk space available on this node //! @param[in] diskSizeAvailable the current amount of disk space available on this node //! @param[in] numberOfCoresMax the maximum number of cores available on this node //! @param[in] numberOfCoresAvailable the current number of cores available on this node //! @param[in] sPublicSubnets the available public subnet for this node //! @param[in] sHypervisor node's hypervisor //! //! @return a pointer to the newly allocated resource structure or NULL if any error occured. //! //! @see free_resource() //! //! @pre The \p sNodeStatus field must not be NULL. //! //! @post On success, a resource structure is allocated and initialized with the given information //! //! @note Caller is responsible to free the allocated memory using the free_resource() function call. //! ncResource *allocate_resource(const char *sNodeStatus, boolean migrationCapable, const char *sIQN, int memorySizeMax, int memorySizeAvailable, int diskSizeMax, int diskSizeAvailable, int numberOfCoresMax, int numberOfCoresAvailable, const char *sPublicSubnets, const char *sHypervisor) { ncResource *pResource = NULL; // Make sure we have a valid parameter if (sNodeStatus == NULL) return (NULL); // See if we can allocate our resource structure if ((pResource = EUCA_ZALLOC(1, sizeof(ncResource))) == NULL) return (NULL); // // Initialize the structure with the given values // euca_strncpy(pResource->nodeStatus, sNodeStatus, CHAR_BUFFER_SIZE); if (sIQN) euca_strncpy(pResource->iqn, sIQN, CHAR_BUFFER_SIZE); pResource->migrationCapable = migrationCapable; if (sPublicSubnets) euca_strncpy(pResource->publicSubnets, sPublicSubnets, CHAR_BUFFER_SIZE); if (sHypervisor) euca_strncpy(pResource->hypervisor, sHypervisor, CHAR_BUFFER_SIZE); pResource->memorySizeMax = memorySizeMax; pResource->memorySizeAvailable = memorySizeAvailable; pResource->diskSizeMax = diskSizeMax; pResource->diskSizeAvailable = diskSizeAvailable; pResource->numberOfCoresMax = numberOfCoresMax; pResource->numberOfCoresAvailable = numberOfCoresAvailable; return (pResource); }
//! //! Serializes the ebs_volume_data struct into a single string that is //! pointed to by the 'dest' argument //! //! @param[in] vol_data //! @param[in] dest //! //! @return //! //! @pre //! //! @post //! //! @note //! int serialize_volume(ebs_volume_data * vol_data, char **dest) { int out_size = -1; char *working_string = NULL; int working_size = -1; if (vol_data == NULL) { LOGTRACE("Cannot serialize a NULL to volume string\n"); return EUCA_ERROR; } working_size = strlen(vol_data->token) + 1 + strlen(vol_data->volumeId) + 1; working_string = EUCA_ZALLOC(1, working_size); if (working_string == NULL) { LOGERROR("Cannot allocate memory!\n"); return EUCA_ERROR; } //Ensure / at end of scURL out_size = snprintf(working_string, working_size, "%s%s,%s", VOLUME_STRING_PREFIX, vol_data->volumeId, vol_data->token); if (out_size <= 0 || out_size > working_size) { EUCA_FREE(working_string); return EUCA_ERROR; } LOGTRACE("Serialized volume struct into %s\n", working_string); *dest = working_string; return EUCA_OK; }
//! //! Clones an existing instance structure //! //! @param[in] old_instance a pointer to the instance to duplicate //! //! @return A clone of the existing instance of NULL on failure //! //! @see free_instance(), allocate_instance() //! //! @pre The \p old_instance field must not be NULL //! //! @post A clone of our existing instance is created. //! //! @note The caller is responsible to free the allocated instance using the free_instance() API. //! ncInstance *clone_instance(const ncInstance * old_instance) { ncInstance *new_instance; // zeroed out for cleaner-looking checkpoints and strings that are empty unless set if ((new_instance = EUCA_ZALLOC(1, sizeof(ncInstance))) == NULL) return (NULL); //! @TODO do not just copy everything memcpy(new_instance, old_instance, sizeof(ncInstance)); return new_instance; }
//! //! Allocate a metadata structure and initialize it. Metadata is present in every type of nc request //! //! @param[in] sCorrelationId the correlation identifier string //! @param[in] sUserId the user identifier //! //! @return a pointer to the newly allocated metadata structure or NULL if any error occured. //! //! @see free_metadata() //! //! @post A metadata structure is allocated and initialized with the provided information //! //! @note Caller is responsible for freeing the allocated memory using free_metadata() call. //! ncMetadata *allocate_metadata(const char *sCorrelationId, const char *sUserId) { ncMetadata *pMeta; // Try to allocate the structure if ((pMeta = EUCA_ZALLOC(1, sizeof(ncMetadata))) == NULL) return (NULL); // // Initialize with the provided information // pMeta->correlationId = ((sCorrelationId != NULL) ? strdup(sCorrelationId) : NULL); pMeta->userId = ((sUserId != NULL) ? strdup(sUserId) : NULL); return (pMeta); }
//! //! Initialize the network driver. //! //! @param[in] pConfig a pointer to our application configuration //! //! @return 0 on success or 1 if any failure occurred. //! //! @see //! //! @pre //! - The core application configuration must be completed prior calling //! - The driver should not be already initialized (if its the case, a no-op will occur) //! - The pConfig parameter must not be NULL //! //! @post //! On success the driver is properly configured. On failure, the state of //! the driver is non-deterministic. If the driver was previously initialized, //! this will result into a no-op. //! //! @note //! static int network_driver_init(eucanetdConfig * pConfig) { int rc = 0; LOGINFO("Initializing '%s' network driver.\n", DRIVER_NAME()); // Make sure our given pointer is valid if (!pConfig) { LOGERROR("Failure to initialize '%s' networking mode. Invalid configuration parameter provided.\n", DRIVER_NAME()); return (1); } // Are we already initialized? if (IS_INITIALIZED()) { LOGERROR("Networking '%s' mode already initialized. Skipping!\n", DRIVER_NAME()); return (0); } if ((pMidoConfig = EUCA_ZALLOC(1, sizeof (mido_config))) == NULL) { LOGERROR("Failed to initialize '%s' networking mode. Out of memory!\n", DRIVER_NAME()); return (1); } rc = initialize_mido(pMidoConfig, pConfig->eucahome, pConfig->flushmode, pConfig->disable_l2_isolation, pConfig->midoeucanetdhost, pConfig->midogwhosts, pConfig->midopubnw, pConfig->midopubgwip, "169.254.0.0", "17"); if (rc) { LOGERROR("could not initialize mido: please ensure that all required config options for VPCMIDO mode are set in eucalyptus.conf\n"); EUCA_FREE(pMidoConfig); return (1); } // Release unnecessary handlers if (pConfig->ipt) { ipt_handler_close(pConfig->ipt); } if (pConfig->ips) { ips_handler_close(pConfig->ips); } if (pConfig->ebt) { ebt_handler_close(pConfig->ebt); } // We are now initialized gInitialized = TRUE; return (0); }
//! //! //! //! @param[in] file //! @param[in] size //! @param[in] mode //! //! @return the newly allocated string or NULL if any error occured //! //! @note caller is responsible to free the allocated memory //! char *file2str_seek(char *file, size_t size, int mode) { int rc = 0; int fd = 0; char *ret = NULL; struct stat statbuf = { 0 }; if (!file || size <= 0) { LOGERROR("bad input parameters\n"); return (NULL); } if ((ret = EUCA_ZALLOC(size, sizeof(char))) == NULL) { LOGERROR("out of memory!\n"); return (NULL); } if ((rc = stat(file, &statbuf)) >= 0) { if ((fd = open(file, O_RDONLY)) >= 0) { if (mode == 1) { if ((rc = lseek(fd, (off_t) (-1 * size), SEEK_END)) < 0) { if ((rc = lseek(fd, (off_t) 0, SEEK_SET)) < 0) { LOGERROR("cannot seek\n"); EUCA_FREE(ret); close(fd); return (NULL); } } } rc = read(fd, ret, (size) - 1); close(fd); } else { LOGERROR("cannot open '%s' read-only\n", file); EUCA_FREE(ret); return (NULL); } } else { LOGERROR("cannot stat console_output file '%s'\n", file); EUCA_FREE(ret); return (NULL); } return (ret); }
//! //! Allocates sem structure from an already allocated Posix named semaphore; sem_p/v can //! be used with it; freeing the sem struct also closes the Posix semaphore that was passed //! in. //! //! @param[in] pExternalLock a pointer to the posix semaphore structure to use. //! //! @return a pointer to the newly created semaphore or NULL if any failure occured. //! //! @pre The external_lock parameter must not be NULL //! //! @post On success a new sem structure is allocated and initialized with the external_lock. //! sem *sem_alloc_posix(sem_t * pExternalLock) { sem *pSem = NULL; // Name sure or parameter is valid if (pExternalLock != NULL) { // Allocate memory for our duplicate semaphore if ((pSem = EUCA_ZALLOC(1, sizeof(sem))) == NULL) return (NULL); // Set the dependency pSem->posix = pExternalLock; pSem->name = strdup("unknown"); return (pSem); } return (NULL); }
//! //! Allocate a new bundle task for the given instance //! //! @param[in] pInstance pointer to the instance we're creating a bundling task for //! //! @return A newly allocated pointer to the bundle task structure if successful or NULL if //! the given pInstance structure is NULL or if we cannot allocate memory. //! //! @pre The \p pInstance field must not be NULL //! //! @post A newly allocated structure is allocated and initialized. //! //! @note The caller is responsible for freeing the allocated memory //! bundleTask *allocate_bundleTask(ncInstance * pInstance) { bundleTask *pBundle = NULL; // Make sure out given parameter is valid if (pInstance != NULL) { if ((pBundle = EUCA_ZALLOC(1, sizeof(bundleTask))) == NULL) { LOGERROR("out of memory\n"); return (NULL); } // initialize our newly allocated structure. snprintf(pBundle->instanceId, CHAR_BUFFER_SIZE, "%s", pInstance->instanceId); snprintf(pBundle->state, CHAR_BUFFER_SIZE, "%s", pInstance->bundleTaskStateName); return (pBundle); } return (NULL); }
//! //! Adds an instance to an instance linked list //! //! @param[in,out] ppHead a pointer to the pointer to the head of the list //! @param[in] pInstance a pointer to the instance to add to the list //! //! @return EUCA_OK on success or the following error code: //! \li EUCA_MEMORY_ERROR: if we fail to allocate memory //! \li EUCA_INVALID_ERROR: if any of our parameter does not meet the pre-condition //! \li EUCA_DUPLICATE_ERROR: if the instance is already part of this list //! //! @pre \li Both \p ppHead and \p pInstance field must not be NULL. //! \li The instance must not be part of the list //! //! @post The instance is added to the list. If this is the first instance in the list, //! the \p ppHead value is updated to point to this instance. //! int add_instance(bunchOfInstances ** ppHead, ncInstance * pInstance) { bunchOfInstances *pNew = NULL; bunchOfInstances *pLast = NULL; bunchOfInstances *pNext = NULL; // Make sure our paramters are valid if ((ppHead == NULL) || (pInstance == NULL)) return (EUCA_INVALID_ERROR); // Try to allocate memory for our instance list node if ((pNew = EUCA_ZALLOC(1, sizeof(bunchOfInstances))) == NULL) return (EUCA_MEMORY_ERROR); // Initialize our node pNew->instance = pInstance; pNew->next = NULL; // Are we the first item in this list? if (*ppHead == NULL) { *ppHead = pNew; (*ppHead)->count = 1; } else { pNext = *ppHead; // // Process the list to make sure we're not trying to add a duplicate // do { pLast = pNext; if (!strcmp(pLast->instance->instanceId, pInstance->instanceId)) { EUCA_FREE(pNew); return (EUCA_DUPLICATE_ERROR); } pNext = pLast->next; } while (pLast->next); // We're at the end so add it there. pLast->next = pNew; (*ppHead)->count++; } return (EUCA_OK); }
//! //! Parses the volume string and returns a newly allocated ebs_volume_data structure via the parameter. //! Caller must free the returned structure. //! Format expected: //! sc://volumeId,token. //! OR //! http://schost:port/services/Storage/volumeId,token //! //! @param[in] volume_string containing the encoded volume information //! @param[in] dest a pointer to a pointer for ebs_volume_data, the referenced pointer will be set to newly allocated struct //! //! @return ok|fail //! //! @pre //! //! @post //! //! @note //! int deserialize_volume(char *volume_string, ebs_volume_data ** dest) { if (volume_string == NULL || strlen(volume_string) <= strlen(VOLUME_STRING_PREFIX)) { *dest = NULL; return EUCA_ERROR; } ebs_volume_data *vol_data = EUCA_ZALLOC(1, sizeof(ebs_volume_data)); if (vol_data == NULL) { LOGERROR("Cannot allocate memory!\n"); *dest = NULL; return EUCA_ERROR; } char *volume_start = volume_string + strlen(VOLUME_STRING_PREFIX); //skip the prefix. if (volume_start == NULL) { LOGERROR("Failed parsing token string: %s\n", volume_string); EUCA_FREE(vol_data); return EUCA_ERROR; } char *token_start = strchr(volume_start, ','); if (token_start == NULL) { LOGERROR("Failed parsing token string: %s\n", volume_string); EUCA_FREE(vol_data); return EUCA_ERROR; } token_start += sizeof(char); //Go 1 past the comma delimiter if (euca_strncpy(vol_data->volumeId, volume_start, token_start - volume_start) == NULL) { EUCA_FREE(vol_data); return EUCA_ERROR; } if (euca_strncpy(vol_data->token, token_start, strlen(token_start) + 1) == NULL) { EUCA_FREE(vol_data); return EUCA_ERROR; } *dest = vol_data; return EUCA_OK; }
//! //! //! //! @return //! //! @pre //! //! @note //! int clean_network_state(void) { int rc = 0; int i = 0; char cmd[MAX_PATH] = { 0 }; char file[MAX_PATH] = { 0 }; char rootwrap[MAX_PATH] = { 0 }; char *pidstr = NULL; char *ipstr = NULL; vnetConfig *tmpvnetconfig = NULL; tmpvnetconfig = EUCA_ZALLOC(1, sizeof(vnetConfig)); if (!tmpvnetconfig) { LOGERROR("out of memory\n"); return -1; } memcpy(tmpvnetconfig, vnetconfig, sizeof(vnetConfig)); rc = vnetUnsetMetadataRedirect(tmpvnetconfig); if (rc) { LOGWARN("failed to unset metadata redirect\n"); } for (i = 1; i < NUMBER_OF_PUBLIC_IPS; i++) { if (tmpvnetconfig->publicips[i].ip != 0 && tmpvnetconfig->publicips[i].allocated != 0) { ipstr = hex2dot(tmpvnetconfig->publicips[i].ip); snprintf(cmd, MAX_PATH, EUCALYPTUS_ROOTWRAP " ip addr del %s/32 dev %s", config->eucahome, SP(ipstr), tmpvnetconfig->pubInterface); LOGDEBUG("running command '%s'\n", cmd); rc = system(cmd); rc = rc >> 8; if (rc && rc != 2) { LOGERROR("running cmd '%s' failed: cannot remove ip %s\n", cmd, SP(ipstr)); } EUCA_FREE(ipstr); } }
//! //! Loads an instance structure data from the instance.xml file under the instance's //! work blobstore path. //! //! @param[in] instanceId the instance identifier string (i-XXXXXXXX) //! //! @return A pointer to the instance structure if successful or otherwise NULL. //! //! @pre The instanceId parameter must not be NULL. //! //! @post On success, a newly allocated pointer to the instance is returned where the stateCode //! is set to NO_STATE. //! ncInstance *load_instance_struct(const char *instanceId) { DIR *insts_dir = NULL; char tmp_path[EUCA_MAX_PATH] = ""; char user_paths[EUCA_MAX_PATH] = ""; char checkpoint_path[EUCA_MAX_PATH] = ""; ncInstance *instance = NULL; struct dirent *dir_entry = NULL; struct stat mystat = { 0 }; // Allocate memory for our instance if ((instance = EUCA_ZALLOC(1, sizeof(ncInstance))) == NULL) { LOGERROR("out of memory (for instance struct)\n"); return (NULL); } // We know the instance indentifier euca_strncpy(instance->instanceId, instanceId, sizeof(instance->instanceId)); // we don't know userId, so we'll look for instanceId in every user's // directory (we're assuming that instanceIds are unique in the system) set_path(user_paths, sizeof(user_paths), NULL, NULL); if ((insts_dir = opendir(user_paths)) == NULL) { LOGERROR("failed to open %s\n", user_paths); goto free; } // Scan every path under the user path for one that conaints our instance while ((dir_entry = readdir(insts_dir)) != NULL) { snprintf(tmp_path, sizeof(tmp_path), "%s/%s/%s", user_paths, dir_entry->d_name, instance->instanceId); if (stat(tmp_path, &mystat) == 0) { // found it. Now save our user identifier euca_strncpy(instance->userId, dir_entry->d_name, sizeof(instance->userId)); break; } } // Done with the directory closedir(insts_dir); insts_dir = NULL; // Did we really find one? if (strlen(instance->userId) < 1) { LOGERROR("didn't find instance %s\n", instance->instanceId); goto free; } // set various instance-directory-relative paths in the instance struct set_instance_paths(instance); // Check if there is a binary checkpoint file, used by versions up to 3.3, // and load metadata from it (as part of a "warm" upgrade from 3.3.0 and 3.3.1). set_path(checkpoint_path, sizeof(checkpoint_path), instance, "instance.checkpoint"); set_path(instance->xmlFilePath, sizeof(instance->xmlFilePath), instance, INSTANCE_FILE_NAME); if (check_file(checkpoint_path) == 0) { ncInstance33 instance33; { // read in the checkpoint int fd = open(checkpoint_path, O_RDONLY); if (fd < 0) { LOGERROR("failed to load metadata for %s from %s: %s\n", instance->instanceId, checkpoint_path, strerror(errno)); goto free; } size_t meta_size = (size_t) sizeof(ncInstance33); assert(meta_size <= SSIZE_MAX); // beyond that read() behavior is unspecified ssize_t bytes_read = read(fd, &instance33, meta_size); close(fd); if (bytes_read < meta_size) { LOGERROR("metadata checkpoint for %s (%ld bytes) in %s is too small (< %ld)\n", instance->instanceId, bytes_read, checkpoint_path, meta_size); goto free; } } // Convert the 3.3 struct into the current struct. // Currently, a copy is sufficient, but if ncInstance // ever changes so that its beginning differs from ncInstanc33, // we may have to write something more elaborate or to break // the ability to upgrade from 3.3. We attempt to detect such a // change with the following if-statement, which compares offsets // in the structs of the last member in the 3.3 version. if (((unsigned long)&(instance->last_stat) - (unsigned long)instance) != ((unsigned long)&(instance33.last_stat) - (unsigned long)&instance33)) { LOGERROR("BUG: upgrade from v3.3 is not possible due to changes to instance struct\n"); goto free; } memcpy(instance, &instance33, sizeof(ncInstance33)); LOGINFO("[%s] upgraded instance checkpoint from v3.3\n", instance->instanceId); } else { // no binary checkpoint, so we expect an XML-formatted checkpoint if (read_instance_xml(instance->xmlFilePath, instance) != EUCA_OK) { LOGERROR("failed to read instance XML\n"); goto free; } } // Reset some fields for safety since they would now be wrong instance->stateCode = NO_STATE; instance->params.root = NULL; instance->params.kernel = NULL; instance->params.ramdisk = NULL; instance->params.swap = NULL; instance->params.ephemeral0 = NULL; // fix up the pointers vbr_parse(&(instance->params), NULL); // perform any upgrade-related manipulations to bring the struct up to date // save the struct back to disk after the upgrade routine had a chance to modify it if (gen_instance_xml(instance) != EUCA_OK) { LOGERROR("failed to create instance XML in %s\n", instance->xmlFilePath); goto free; } // remove the binary checkpoint because it is no longer needed and not used past 3.3 unlink(checkpoint_path); return (instance); free: EUCA_FREE(instance); return (NULL); }
//! //! //! //! @param[in] euca_home //! @param[in] rundir_path //! @param[in] instName //! //! @return EUCA_OK on success or proper error code. Known error code returned include: EUCA_ERROR, //! EUCA_IO_ERROR and EUCA_MEMORY_ERROR. //! int make_credential_floppy(char *euca_home, ncInstance * instance) { int fd = 0; int rc = 0; int rbytes = 0; int count = 0; int ret = EUCA_ERROR; char dest_path[1024] = ""; char source_path[1024] = ""; char *ptr = NULL; char *buf = NULL; char *tmp = NULL; char *rundir_path = instance->instancePath; if (!euca_home || !rundir_path || !strlen(euca_home) || !strlen(rundir_path)) { return (EUCA_ERROR); } snprintf(source_path, 1024, EUCALYPTUS_HELPER_DIR "/floppy", euca_home); snprintf(dest_path, 1024, "%s/floppy", rundir_path); if ((buf = EUCA_ALLOC(1024 * 2048, sizeof(char))) == NULL) { ret = EUCA_MEMORY_ERROR; goto cleanup; } if ((fd = open(source_path, O_RDONLY)) < 0) { ret = EUCA_IO_ERROR; goto cleanup; } rbytes = read(fd, buf, 1024 * 2048); close(fd); if (rbytes < 0) { ret = EUCA_IO_ERROR; goto cleanup; } tmp = EUCA_ZALLOC(KEY_STRING_SIZE, sizeof(char)); if (!tmp) { ret = EUCA_MEMORY_ERROR; goto cleanup; } ptr = buf; count = 0; while (count < rbytes) { memcpy(tmp, ptr, strlen("MAGICEUCALYPTUSINSTPUBKEYPLACEHOLDER")); if (!strcmp(tmp, "MAGICEUCALYPTUSINSTPUBKEYPLACEHOLDER")) { memcpy(ptr, instance->instancePubkey, strlen(instance->instancePubkey)); } else if (!strcmp(tmp, "MAGICEUCALYPTUSAUTHPUBKEYPLACEHOLDER")) { memcpy(ptr, instance->euareKey, strlen(instance->euareKey)); } else if (!strcmp(tmp, "MAGICEUCALYPTUSAUTHSIGNATPLACEHOLDER")) { memcpy(ptr, instance->instanceToken, strlen(instance->instanceToken)); } else if (!strcmp(tmp, "MAGICEUCALYPTUSINSTPRIKEYPLACEHOLDER")) { memcpy(ptr, instance->instancePk, strlen(instance->instancePk)); } ptr++; count++; } if ((fd = open(dest_path, O_CREAT | O_TRUNC | O_RDWR, 0700)) < 0) { ret = EUCA_IO_ERROR; goto cleanup; } rc = write(fd, buf, rbytes); close(fd); if (rc != rbytes) { ret = EUCA_IO_ERROR; goto cleanup; } ret = EUCA_OK; cleanup: if (buf != NULL) EUCA_FREE(buf); if (tmp != NULL) EUCA_FREE(tmp); return ret; }
//! //! Allocate a new semaphore with the given name and mutex starting value. //! //! @param[in] val the starting mutex count //! @param[in] typeName the type of semaphore. If 'mutex' then pthread mutexis used if any other //! name then posix named semaphore is used if an empty name then SYS V IPC //! semaphore is implied. //! @param[in] flags Kernel encoding of open mode //! //! @return a pointer to the newly allocated semaphore or NULL if a failure occured //! //! @see sem_free() //! //! @pre The name field must not be NULL. //! //! @post On success, a semaphore structure is allocated and initialized //! //! @note Caller is responsible to free allocated memory for this semaphore. Call to sem_free() is //! prefered for this operation //! sem *sem_realloc(const int val, const char *typeName, u32 flags) { sem *pSem = NULL; char addr[24] = ""; DECLARE_ARG; // Validate the name parameter assert(typeName); // Check if we can allocate memory for our zemaphore if ((pSem = EUCA_ZALLOC(1, sizeof(sem))) == NULL) return (NULL); // Initialize our type independent fields pSem->sysv = -1; pSem->flags = flags; // save the address of this semaphore for future use snprintf(addr, sizeof(addr), "%p", pSem); // // Initialize our semphore base on the requested type // if (!strcmp(typeName, IPC_MUTEX_SEMAPHORE)) { // use pthread mutex pSem->usemutex = 1; pSem->mutcount = val; pSem->mutwaiters = 0; pthread_mutex_init(&(pSem->mutex), NULL); pthread_cond_init(&(pSem->cond), NULL); // In this case we'll use the address of the semaphore rather than the name pSem->name = strdup(addr); } else if (strlen(typeName) > 0) { // named semaphores if (pSem->flags & O_EXCL) { // clean up in case previous sem holder crashed if (sem_unlink(typeName) == 0) { LOGINFO("cleaning up old semaphore %s\n", typeName); } } // Create a new semaphore with this name. if ((pSem->posix = sem_open(typeName, O_CREAT | flags, 0644, val)) == SEM_FAILED) { EUCA_FREE(pSem); return (NULL); } pSem->name = strdup(typeName); } else { // SYS V IPC semaphores if ((pSem->sysv = semget(IPC_PRIVATE, 1, (IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR))) < 0) { EUCA_FREE(pSem); return (NULL); } // Set the value arg.val = val; if (semctl(pSem->sysv, 0, SETVAL, arg) == -1) { EUCA_FREE(pSem); return (NULL); } // In this case we'll use the address of the semaphore rather than the name pSem->name = strdup(addr); } return (pSem); }
//! //! //! //! @param[in] describeServices //! @param[in] env pointer to the AXIS2 environment structure //! //! @return //! //! @pre //! //! @note //! adb_DescribeServicesResponse_t *DescribeServicesMarshal(adb_DescribeServices_t * describeServices, const axutil_env_t * env) { adb_DescribeServicesResponse_t *ret = NULL; adb_describeServicesResponseType_t *adbresp = NULL; adb_describeServicesType_t *adbinput = NULL; int rc; axis2_bool_t status = AXIS2_TRUE; char statusMessage[256]; ncMetadata ccMeta; serviceStatusType *outStatuses = NULL; serviceInfoType *serviceIds = NULL; int serviceIdsLen = 0, outStatusesLen = 0, i; adbinput = adb_DescribeServices_get_DescribeServices(describeServices, env); adbresp = adb_describeServicesResponseType_create(env); EUCA_MESSAGE_UNMARSHAL(describeServicesType, adbinput, (&ccMeta)); adb_describeServicesResponseType_set_correlationId(adbresp, env, adb_describeServicesType_get_correlationId(adbinput, env)); adb_describeServicesResponseType_set_userId(adbresp, env, adb_describeServicesType_get_userId(adbinput, env)); // localDev = adb_describeServicesType_get_localDev(adbinput, env); serviceIdsLen = adb_describeServicesType_sizeof_serviceIds(adbinput, env); serviceIds = EUCA_ZALLOC(serviceIdsLen, sizeof(serviceInfoType)); for (i = 0; i < serviceIdsLen; i++) { copy_service_info_type_from_adb(&(serviceIds[i]), adb_describeServicesType_get_serviceIds_at(adbinput, env, i), env); } status = AXIS2_TRUE; rc = doDescribeServices(&ccMeta, serviceIds, serviceIdsLen, &outStatuses, &outStatusesLen); if (rc) { logprintf("ERROR: doDescribeServices() returned FAIL\n"); status = AXIS2_FALSE; snprintf(statusMessage, 255, "ERROR"); } for (i = 0; i < outStatusesLen; i++) { adb_serviceStatusType_t *stt; adb_serviceInfoType_t *sit; stt = adb_serviceStatusType_create(env); adb_serviceStatusType_set_localState(stt, env, outStatuses[i].localState); adb_serviceStatusType_set_localEpoch(stt, env, outStatuses[i].localEpoch); adb_serviceStatusType_add_details(stt, env, outStatuses[i].details); sit = copy_service_info_type_to_adb(env, &(outStatuses[i].serviceId)); adb_serviceStatusType_set_serviceId(stt, env, sit); adb_describeServicesResponseType_add_serviceStatuses(adbresp, env, stt); } EUCA_FREE(outStatuses); EUCA_FREE(serviceIds); adb_describeServicesResponseType_set_return(adbresp, env, status); if (status == AXIS2_FALSE) { adb_describeServicesResponseType_set_statusMessage(adbresp, env, statusMessage); } ret = adb_DescribeServicesResponse_create(env); adb_DescribeServicesResponse_set_DescribeServicesResponse(ret, env, adbresp); return (ret); }
//! //! //! //! @param[in] req //! //! @return EUCA_OK on success or EUCA_ERROR on failure //! int prepare_validate(imager_request * req) { int i = 0; int num_sda_parts = 0; imager_param *p = NULL; prepare_params *state = NULL; print_req(req); if ((state = EUCA_ZALLOC(1, sizeof(prepare_params))) == NULL) err("out of memory"); // set defaults state->bootable = FALSE; state->cache = TRUE; state->work = FALSE; state->action = ACTION_DOWNLOAD | ACTION_CONVERT; // record in 'state' all specified parameters for (p = req->params; p != NULL && p->key != NULL; p++) { if (strcmp(p->key, _CACHE) == 0) { state->cache = parse_boolean(p->val); } else if (strcmp(p->key, _BOOT) == 0) { state->bootable = parse_boolean(p->val); } else if (strcmp(p->key, _ID) == 0) { state->id = p->val; } else if (strcmp(p->key, _KEY) == 0) { state->sshkey = parse_loginpassword(p->val); } else if (strcmp(p->key, _OUT) == 0) { state->out = p->val; } else if (strcmp(p->key, _WORK) == 0) { state->work = parse_boolean(p->val); } else if (strcmp(p->key, _VBR) == 0) { if (state->total_vbrs == (EUCA_MAX_VBRS - 1)) err("too many vbr= parameters"); state->vbrs[state->total_vbrs++] = p->val; if (strstr(p->val, ":sda1:") != NULL || strstr(p->val, ":sda2:") != NULL || strstr(p->val, ":sda3:") != NULL) { num_sda_parts++; } } else if (strcmp(p->key, _ACTION) == 0) { if (strcmp(p->val, "download") == 0) { state->action = ACTION_DOWNLOAD; } else if (strcmp(p->val, "convert") == 0) { state->action = ACTION_CONVERT; } else { err("unknown action parameter '%s' for command 'prepare'", p->val); } } else { err("invalid parameter '%s' for command 'prepare'", p->key); } } // ensure mandatory params are present if (state->total_vbrs < 1) err("not a single VBR was specified"); LOGINFO("actions: download=%s convert=%s\n", (state->action & ACTION_DOWNLOAD) ? ("yes") : ("no"), (state->action & ACTION_CONVERT) ? ("yes") : ("no")) // if a bootable disk is requested and the expected number of partitions is present, // then add the boot VBR entry so an extra, 4th, boot partition will get created if (state->bootable && num_sda_parts > 0) { char buf[1024]; snprintf(buf, sizeof(buf), BOOT_VBR_FORMAT, num_sda_parts+1); state->vbrs[state->total_vbrs++] = strdup(buf); } for (i = 0; i < state->total_vbrs; i++) { if (vbr_add_ascii(state->vbrs[i], &(state->vm))) err("failed to add VBR record '%s'", state->vbrs[i]); } if (vbr_parse(&(state->vm), NULL) != EUCA_OK) err("failed to validate VBR records"); // if given an empty key file, just set the pointer to NULL if (state->sshkey && strlen(state->sshkey) == 0) { EUCA_FREE(state->sshkey); } // save pointer to find it later req->internal = ((void *)state); return (EUCA_OK); }
//! //! Allocate a new MAP entry //! //! @param[in] size unused parameter //! //! @return a pointer to the new map entry structure or NULL if any error occured //! map *map_create(int size) { return ((map *) EUCA_ZALLOC(1, sizeof(map))); }
//! //! Creates and initialize an NC stub entry //! //! @param[in] endpoint_uri the endpoint URI string //! @param[in] logfile the log file name string //! @param[in] homedir the home directory path string //! //! @return a pointer to the newly created NC stub structure //! ncStub *ncStubCreate(char *endpoint_uri, char *logfile, char *homedir) { return (EUCA_ZALLOC(1, sizeof(ncStub))); }
//! //! //! //! @param[in] pMeta a pointer to the node controller (NC) metadata structure //! @param[in] serviceIds a list of service info. //! @param[in] serviceIdsLen the number of service info in the serviceIds list //! @param[out] outStatuses list of service status //! @param[out] outStatusesLen number of service status in the outStatuses list //! //! @return //! //! @pre //! //! @note //! int doDescribeServices(ncMetadata * pMeta, serviceInfoType * serviceIds, int serviceIdsLen, serviceStatusType ** outStatuses, int *outStatusesLen) { int rc = 0; int i = 0; int j = 0; int port = 0; char uri[MAX_PATH] = { 0 }; char uriType[32] = { 0 }; char host[MAX_PATH] = { 0 }; char path[MAX_PATH] = { 0 }; serviceStatusType *myStatus = NULL; int do_report_cluster = 1; // always do report on the cluster, otherwise CC won't get ENABLED int do_report_nodes = 0; int do_report_all = 0; char *my_partition = NULL; rc = initialize(pMeta, TRUE); // DescribeServices is the only authoritative source of epoch if (rc) { return (1); } LOGDEBUG("invoked: userId=%s, serviceIdsLen=%d\n", SP(pMeta ? pMeta->userId : "UNKNOWN"), serviceIdsLen); //! @TODO for now, return error if list of services is passed in as parameter /* if (serviceIdsLen > 0) { LOGERROR("DescribeServices(): received non-zero number of input services, returning fail\n"); *outStatusesLen = 0; *outStatuses = NULL; return(1); } */ sem_mywait(CONFIG); { if (!strcmp(config->ccStatus.serviceId.name, "self")) { for (i = 0; i < serviceIdsLen; i++) { LOGDEBUG("received input serviceId[%d]\n", i); if (strlen(serviceIds[i].type)) { if (!strcmp(serviceIds[i].type, "cluster")) { snprintf(uri, MAX_PATH, "%s", serviceIds[i].uris[0]); rc = tokenize_uri(uri, uriType, host, &port, path); if (strlen(host)) { LOGDEBUG("setting local serviceId to input serviceId (type=%s name=%s partition=%s)\n", SP(serviceIds[i].type), SP(serviceIds[i].name), SP(serviceIds[i].partition)); memcpy(&(config->ccStatus.serviceId), &(serviceIds[i]), sizeof(serviceInfoType)); } } else if (!strcmp(serviceIds[i].type, "node")) { do_report_nodes = 1; // report on node services if requested explicitly } } } } } sem_mypost(CONFIG); if (serviceIdsLen < 1) { // if the describe request is not specific, report on everything do_report_cluster = 1; do_report_nodes = 1; do_report_all = 1; } else { // if the describe request is specific, identify which types are requested do_report_cluster = 0; do_report_nodes = 0; do_report_all = 0; for (i = 0; i < serviceIdsLen; i++) { LOGDEBUG("received input serviceId[%d]: %s %s %s %s\n", i, serviceIds[i].type, serviceIds[i].partition, serviceIds[i].name, serviceIds[i].uris[0]); if (strlen(serviceIds[i].type)) { if (!strcmp(serviceIds[i].type, "cluster")) { do_report_cluster = 1; // report on cluster services if requested explicitly } else if (!strcmp(serviceIds[i].type, "node")) { do_report_nodes++; // count number of and report on node services if requested explicitly } } } } for (i = 0; i < 16; i++) { if (strlen(config->services[i].type)) { LOGDEBUG("internal serviceInfos type=%s name=%s partition=%s urisLen=%d\n", config->services[i].type, config->services[i].name, config->services[i].partition, config->services[i].urisLen); if (!strcmp(config->services[i].type, "cluster")) { my_partition = config->services[i].partition; } for (j = 0; j < MAX_SERVICE_URIS; j++) { if (strlen(config->services[i].uris[j])) { LOGDEBUG("internal serviceInfos\t uri[%d]:%s\n", j, config->services[i].uris[j]); } } } } for (i = 0; i < 16; i++) { if (strlen(config->disabledServices[i].type)) { LOGDEBUG("internal disabled serviceInfos type=%s name=%s partition=%s urisLen=%d\n", config->disabledServices[i].type, config->disabledServices[i].name, config->disabledServices[i].partition, config->disabledServices[i].urisLen); for (j = 0; j < MAX_SERVICE_URIS; j++) { if (strlen(config->disabledServices[i].uris[j])) { LOGDEBUG("internal disabled serviceInfos\t uri[%d]:%s\n", j, config->disabledServices[i].uris[j]); } } } } for (i = 0; i < 16; i++) { if (strlen(config->notreadyServices[i].type)) { LOGDEBUG("internal not ready serviceInfos type=%s name=%s partition=%s urisLen=%d\n", config->notreadyServices[i].type, config->notreadyServices[i].name, config->notreadyServices[i].partition, config->notreadyServices[i].urisLen); for (j = 0; j < MAX_SERVICE_URIS; j++) { if (strlen(config->notreadyServices[i].uris[j])) { LOGDEBUG("internal not ready serviceInfos\t uri[%d]:%s\n", j, config->notreadyServices[i].uris[j]); } } } } *outStatusesLen = 0; *outStatuses = NULL; if (do_report_cluster) { (*outStatusesLen) += 1; *outStatuses = EUCA_ZALLOC(1, sizeof(serviceStatusType)); if (!*outStatuses) { LOGFATAL("out of memory!\n"); unlock_exit(1); } myStatus = *outStatuses; snprintf(myStatus->localState, 32, "%s", config->ccStatus.localState); // ENABLED, DISABLED, STOPPED, NOTREADY snprintf(myStatus->details, 1024, "%s", config->ccStatus.details); // string that gets printed by 'euca-describe-services -E' myStatus->localEpoch = config->ccStatus.localEpoch; memcpy(&(myStatus->serviceId), &(config->ccStatus.serviceId), sizeof(serviceInfoType)); LOGDEBUG("external services\t uri[%d]: %s %s %s %s %s\n", 0, myStatus->serviceId.type, myStatus->serviceId.partition, myStatus->serviceId.name, myStatus->localState, myStatus->serviceId.uris[0]); } if (do_report_nodes) { extern ccResourceCache *resourceCache; ccResourceCache resourceCacheLocal; sem_mywait(RESCACHE); memcpy(&resourceCacheLocal, resourceCache, sizeof(ccResourceCache)); sem_mypost(RESCACHE); if (resourceCacheLocal.numResources > 0 && my_partition != NULL) { // parition is unknown at early stages of CC initialization for (int idIdx = 0; idIdx < serviceIdsLen; idIdx++) { if (do_report_all || !strcmp(serviceIds[idIdx].type, "node")) { for (int rIdx = 0; rIdx < resourceCacheLocal.numResources; rIdx++) { ccResource *r = resourceCacheLocal.resources + rIdx; if (do_report_all || (strlen(serviceIds[idIdx].name) && strlen(r->ip) && !strcmp(serviceIds[idIdx].name, r->ip))) { // we have a node that we want to report about (*outStatusesLen) += 1; *outStatuses = EUCA_REALLOC(*outStatuses, *outStatusesLen, sizeof(serviceStatusType)); if (*outStatuses == NULL) { LOGFATAL("out of memory! (outStatusesLen=%d)\n", *outStatusesLen); unlock_exit(1); } myStatus = *outStatuses + *outStatusesLen - 1; { int resState = r->state; int resNcState = r->ncState; char *state = "BUGGY"; char *msg = ""; if (resState == RESUP) { if (resNcState == ENABLED) { state = "ENABLED"; msg = "the node is operating normally"; } else if (resNcState == STOPPED) { state = "STOPPED"; msg = "the node is not accepting new instances"; } else if (resNcState == NOTREADY) { state = "NOTREADY"; if (strnlen(r->nodeMessage, 1024)) { msg = r->nodeMessage; } else { msg = "the node is currently experiencing problems and needs attention"; } } } else if (resState == RESASLEEP || resState == RESWAKING) { state = "NOTREADY"; msg = "the node is currently in the sleep state"; } else if (resState == RESDOWN) { state = "NOTREADY"; if (strnlen(r->nodeMessage, 1024)) { msg = r->nodeMessage; } else { msg = "the node is not responding to the cluster controller"; } } snprintf(myStatus->localState, 32, "%s", state); snprintf(myStatus->details, 1024, "%s", msg); // string that gets printed by 'euca-describe-services -E' } myStatus->localEpoch = config->ccStatus.localEpoch; sprintf(myStatus->serviceId.type, "node"); sprintf(myStatus->serviceId.name, r->hostname); sprintf(myStatus->serviceId.partition, config->ccStatus.serviceId.partition); sprintf(myStatus->serviceId.uris[0], r->ncURL); myStatus->serviceId.urisLen = 1; LOGDEBUG("external services\t uri[%d]: %s %s %s %s %s\n", idIdx, myStatus->serviceId.type, myStatus->serviceId.partition, myStatus->serviceId.name, myStatus->localState, myStatus->serviceId.uris[0]); } } } } } } LOGDEBUG("done\n"); return (0); }
//! //! Allocate and initialize an instance structure with given information. Instances are //! present in instance-related requests. //! //! @param[in] sUUID the unique user identifier string //! @param[in] sInstanceId the instance identifier string (i-XXXXXXXX) //! @param[in] sReservationId the reservation identifier string //! @param[in] pVirtMachine a pointer to our virtual machine parametes //! @param[in] sStateName the current instance state name string //! @param[in] stateCode the current instance state code //! @param[in] sUserId the user identifier string //! @param[in] sOwnerId the owner identifier string //! @param[in] sAccountId the account identifier string //! @param[in] pNetCfg a pointer to the network configuration of this instance //! @param[in] sKeyName the SSH key name to use //! @param[in] sUserData user data string to pass to the instance //! @param[in] sLaunchIndex the instance's launch index //! @param[in] sPlatform the instance's platform type //! @param[in] expiryTime the instance's expiration time before it reaches running //! @param[in] asGroupNames an array list of group name string //! @param[in] groupNamesSize the number of group name in the asGroupNames list //! @param[in] asGroupIds an array list of group identifier string //! @param[in] groupIdsSize the number of group name in the asGroupIds list //! //! @return a pointer to the newly allocated instance structure or NULL if any error occured. //! //! @see add_instance() //! @see free_instance() //! //! @post On succes an instance structure is allocated and initialized with the given information. //! ncInstance *allocate_instance(const char *sUUID, const char *sInstanceId, const char *sReservationId, virtualMachine * pVirtMachine, const char *sStateName, int stateCode, const char *sUserId, const char *sOwnerId, const char *sAccountId, netConfig * pNetCfg, const char *sKeyName, const char *sUserData, const char *sLaunchIndex, const char *sPlatform, int expiryTime, char **asGroupNames, int groupNamesSize, char **asGroupIds, int groupIdsSize) { u32 i = 0; ncInstance *pInstance = NULL; /* zeroed out for cleaner-looking checkpoints and strings that are empty unless set */ if ((pInstance = EUCA_ZALLOC(1, sizeof(ncInstance))) == NULL) return (NULL); if (sUserData) euca_strncpy(pInstance->userData, sUserData, CHAR_BUFFER_SIZE * 32); if (sLaunchIndex) euca_strncpy(pInstance->launchIndex, sLaunchIndex, CHAR_BUFFER_SIZE); if (sPlatform) euca_strncpy(pInstance->platform, sPlatform, CHAR_BUFFER_SIZE); pInstance->groupNamesSize = groupNamesSize; if ((asGroupNames != NULL) && (groupNamesSize > 0)) { for (i = 0; i < groupNamesSize && asGroupNames[i]; i++) euca_strncpy(pInstance->groupNames[i], asGroupNames[i], CHAR_BUFFER_SIZE); } pInstance->groupIdsSize = groupIdsSize; if ((asGroupIds != NULL) && (groupIdsSize > 0)) { for (i = 0; i < groupIdsSize && asGroupIds[i]; i++) euca_strncpy(pInstance->groupIds[i], asGroupIds[i], CHAR_BUFFER_SIZE); } if (pNetCfg != NULL) memcpy(&(pInstance->ncnet), pNetCfg, sizeof(netConfig)); if (sUUID) euca_strncpy(pInstance->uuid, sUUID, CHAR_BUFFER_SIZE); if (sInstanceId) euca_strncpy(pInstance->instanceId, sInstanceId, CHAR_BUFFER_SIZE); if (sKeyName) euca_strncpy(pInstance->keyName, sKeyName, CHAR_BUFFER_SIZE * 4); if (sReservationId) euca_strncpy(pInstance->reservationId, sReservationId, CHAR_BUFFER_SIZE); if (sStateName) euca_strncpy(pInstance->stateName, sStateName, CHAR_BUFFER_SIZE); if (sUserId) euca_strncpy(pInstance->userId, sUserId, CHAR_BUFFER_SIZE); if (sOwnerId) euca_strncpy(pInstance->ownerId, sOwnerId, CHAR_BUFFER_SIZE); if (sAccountId) euca_strncpy(pInstance->accountId, sAccountId, CHAR_BUFFER_SIZE); if (pVirtMachine) memcpy(&(pInstance->params), pVirtMachine, sizeof(virtualMachine)); pInstance->stateCode = stateCode; euca_strncpy(pInstance->bundleTaskStateName, bundling_progress_names[NOT_BUNDLING], CHAR_BUFFER_SIZE); pInstance->expiryTime = expiryTime; return (pInstance); }
//! //! Creates and initialize an NC stub entry //! //! @param[in] endpoint_uri the endpoint URI string //! @param[in] logfile the log file name string //! @param[in] homedir the home directory path string //! //! @return a pointer to the newly created NC stub structure //! scStub *scStubCreate(char *endpoint_uri, char *logfile, char *homedir) { char *uri = NULL; char *p = NULL; char *node_name = NULL; scStub *pStub = NULL; axutil_env_t *env = NULL; axis2_char_t *client_home; axis2_stub_t *stub; if (logfile) { env = axutil_env_create_all(logfile, AXIS2_LOG_LEVEL_TRACE); } else { env = axutil_env_create_all(NULL, 0); } if (homedir) { client_home = (axis2_char_t *) homedir; } else { client_home = AXIS2_GETENV("AXIS2C_HOME"); } if (client_home == NULL) { LOGERROR("cannot get AXIS2C_HOME"); return NULL; } if (endpoint_uri == NULL) { LOGERROR("empty endpoint_url"); return NULL; } uri = endpoint_uri; // extract node name from the endpoint p = strstr(uri, "://"); // find "http[s]://..." if (p == NULL) { LOGERROR("received invalid URI %s\n", uri); return NULL; } node_name = strdup(p + 3); // copy without the protocol prefix if (node_name == NULL) { LOGERROR("is out of memory\n"); return NULL; } if ((p = strchr(node_name, ':')) != NULL) *p = '\0'; // cut off the port if ((p = strchr(node_name, '/')) != NULL) *p = '\0'; // if there is no port //! @todo what if endpoint_uri, home, or env are NULL? stub = axis2_stub_create_EucalyptusSC(env, client_home, (axis2_char_t *) uri); if (stub) { if ((pStub = EUCA_ZALLOC(1, sizeof(scStub))) != NULL) { pStub->env = env; pStub->client_home = strdup((char *)client_home); pStub->endpoint_uri = (axis2_char_t *) strdup(endpoint_uri); pStub->node_name = (axis2_char_t *) strdup(node_name); pStub->stub = stub; if (pStub->client_home == NULL || pStub->endpoint_uri == NULL || pStub->node_name == NULL) { LOGWARN("out of memory (%s:%s:%d client_home=%s endpoint_uri=%s node_name=%s)", __FILE__, __FUNCTION__, __LINE__, pStub->client_home, pStub->endpoint_uri, pStub->node_name); } } else { LOGWARN("out of memory for 'st' (%s:%s:%d)\n", __FILE__, __FUNCTION__, __LINE__); } } else { LOGERROR("failed to create a stub for EucalyptusNC service (stub=%p env=%p client_home=%s)\n", stub, env, client_home); } EUCA_FREE(node_name); return (pStub); }
//! //! find value of the given param in the eucalyptus.conf, //! return NULL if the param is commented out //! //! @param[in] eucahome the path where Eucalyptus is installed //! @param[in] param the parameter value we're looking for //! //! @return the matching value or NULL //! static char *find_conf_value(const char *eucahome, const char *param) { int i = 0; int j = 0; int quote = 0; char *pch = NULL; char conf_path[1024] = ""; char line[1024] = ""; char *value = NULL; FILE *f_conf = NULL; if (!eucahome || !param) return (NULL); snprintf(conf_path, 1024, EUCALYPTUS_CONF_LOCATION, eucahome); if ((f_conf = fopen(conf_path, "r")) == NULL) { return (NULL); } while (fgets(line, 1024, f_conf) != NULL) { if (strstr(line, param) != NULL) { // found the param in the line if (strchr(line, '#') != NULL) { // the line is commented out (assume # can't appear in the middle) break; } else { pch = strtok(line, "="); // again assume '=' can't appear in the middle of value pch = strtok(NULL, "="); if (pch && (strlen(pch) > 0)) { if ((value = EUCA_ZALLOC(strlen(pch) + 1, 1)) == NULL) { fclose(f_conf); return (NULL); } snprintf(value, strlen(pch) + 1, "%s", pch); } break; } } bzero(line, 1024); } // remove "" from the value if (value) { quote = 0; for (i = 0; i < strlen(value); i++) { if (value[i] == '\"') quote++; else value[i - quote] = value[i]; } value[strlen(value) - quote] = 0x00; // remove spaces i = 0; while ((value[i] == ' ') || (value[i] == '\t')) i++; for (j = i; j < strlen(value); j++) value[j - i] = value[j]; value[strlen(value) - i] = 0x00; if (value[strlen(value) - 1] == '\n') value[strlen(value) - 1] = 0x00; } fclose(f_conf); return (value); }
//! //! Creates and initialize an NC stub entry //! //! @param[in] endpoint_uri the endpoint URI string //! @param[in] logfile the log file name string //! @param[in] homedir the home directory path string //! //! @return a pointer to the newly created NC stub structure //! ncStub *ncStubCreate(char *endpoint_uri, char *logfile, char *homedir) { char *uri = NULL; char *p = NULL; char *node_name = NULL; axutil_env_t *env = NULL; axis2_char_t *client_home = NULL; axis2_stub_t *stub = NULL; ncStub *st = NULL; if (logfile) { env = axutil_env_create_all(logfile, AXIS2_LOG_LEVEL_TRACE); } else { env = axutil_env_create_all(NULL, 0); } if (homedir) { client_home = (axis2_char_t *) homedir; } else { client_home = AXIS2_GETENV("AXIS2C_HOME"); } if (client_home == NULL) { LOGERROR("fakeNC: ERROR: cannot get AXIS2C_HOME"); return NULL; } if (endpoint_uri == NULL) { LOGERROR("fakeNC: ERROR: empty endpoint_url"); return NULL; } uri = endpoint_uri; // extract node name from the endpoint p = strstr(uri, "://"); // find "http[s]://..." if (p == NULL) { LOGERROR("fakeNC: ncStubCreate received invalid URI %s\n", uri); return NULL; } node_name = strdup(p + 3); // copy without the protocol prefix if (node_name == NULL) { LOGERROR("fakeNC: ncStubCreate is out of memory\n"); return NULL; } if ((p = strchr(node_name, ':')) != NULL) *p = '\0'; // cut off the port if ((p = strchr(node_name, '/')) != NULL) *p = '\0'; // if there is no port LOGDEBUG("fakeNC: DEBUG: requested URI %s\n", uri); // see if we should redirect to a local broker if (strstr(uri, "EucalyptusBroker")) { uri = "http://localhost:8773/services/EucalyptusBroker"; LOGDEBUG("fakeNC: DEBUG: redirecting request to %s\n", uri); } //! @todo what if endpoint_uri, home, or env are NULL? stub = axis2_stub_create_EucalyptusNC(env, client_home, (axis2_char_t *) uri); if (stub && (st = EUCA_ZALLOC(1, sizeof(ncStub)))) { st->env = env; st->client_home = strdup((char *)client_home); st->endpoint_uri = (axis2_char_t *) strdup(endpoint_uri); st->node_name = (axis2_char_t *) strdup(node_name); st->stub = stub; if (st->client_home == NULL || st->endpoint_uri == NULL) { LOGWARN("fakeNC: WARNING: out of memory"); } } else { LOGWARN("fakeNC: WARNING: out of memory"); } EUCA_FREE(node_name); return (st); }
//! //! Handles the console output retrieval request. //! //! @param[in] nc a pointer to the NC state structure to initialize //! @param[in] pMeta a pointer to the node controller (NC) metadata structure //! @param[in] instanceId the instance identifier string (i-XXXXXXXX) //! @param[out] consoleOutput a pointer to the unallocated string that will contain the output //! //! @return EUCA_OK on success or EUCA_ERROR and EUCA_NOT_FOUND_ERROR on failure. //! static int doGetConsoleOutput(struct nc_state_t *nc, ncMetadata * pMeta, char *instanceId, char **consoleOutput) { int rc = 0; int fd = 0; int ret = EUCA_OK; int readsize = 0; char *console_output = NULL; char *console_append = NULL; char *console_main = NULL; char console_file[MAX_PATH] = ""; char userId[48] = ""; ncInstance *instance = NULL; struct stat statbuf = { 0 }; *consoleOutput = NULL; readsize = 64 * 1024; // find the instance record sem_p(inst_sem); { if ((instance = find_instance(&global_instances, instanceId)) != NULL) { snprintf(console_file, 1024, "%s/console.append.log", instance->instancePath); snprintf(userId, 48, "%s", instance->userId); } } sem_v(inst_sem); if (!instance) { logprintfl(EUCAERROR, "[%s] cannot locate instance\n", instanceId); return (EUCA_NOT_FOUND_ERROR); } // read from console.append.log if it exists into dynamically allocated 4K console_append buffer if ((rc = stat(console_file, &statbuf)) >= 0) { if (diskutil_ch(console_file, nc->admin_user_id, nc->admin_user_id, 0) != EUCA_OK) { logprintfl(EUCAERROR, "[%s] failed to change ownership of %s\n", instanceId, console_file); return (EUCA_ERROR); } if ((fd = open(console_file, O_RDONLY)) >= 0) { if ((console_append = EUCA_ZALLOC(4096, sizeof(char))) != NULL) { rc = read(fd, console_append, (4096) - 1); } close(fd); } } sem_p(inst_sem); { snprintf(console_file, MAX_PATH, "%s/console.log", instance->instancePath); } sem_v(inst_sem); // read the last 64K from console.log or the whole file, if smaller, into dynamically allocated 64K console_main buffer if ((rc = stat(console_file, &statbuf)) >= 0) { if (diskutil_ch(console_file, nc->admin_user_id, nc->admin_user_id, 0) != EUCA_OK) { logprintfl(EUCAERROR, "[%s] failed to change ownership of %s\n", instanceId, console_file); EUCA_FREE(console_append); return (EUCA_ERROR); } if ((fd = open(console_file, O_RDONLY)) >= 0) { if ((rc = lseek(fd, (off_t) (-1 * readsize), SEEK_END)) < 0) { if ((rc = lseek(fd, (off_t) 0, SEEK_SET)) < 0) { logprintfl(EUCAERROR, "[%s] cannot seek to beginning of file\n", instanceId); if (console_append) EUCA_FREE(console_append); close(fd); return (EUCA_ERROR); } } if ((console_main = EUCA_ZALLOC(readsize, sizeof(char))) != NULL) { rc = read(fd, console_main, (readsize) - 1); } close(fd); } else { logprintfl(EUCAERROR, "[%s] cannot open '%s' read-only\n", instanceId, console_file); } } else { logprintfl(EUCAERROR, "[%s] cannot stat console_output file '%s'\n", instanceId, console_file); } // concatenate console_append with console_main, base64-encode this, and put into dynamically allocated buffer consoleOutput ret = EUCA_ERROR; if ((console_output = EUCA_ZALLOC((readsize) + 4096, sizeof(char))) != NULL) { if (console_append) { strncat(console_output, console_append, 4096); } if (console_main) { strncat(console_output, console_main, readsize); } *consoleOutput = base64_enc((unsigned char *)console_output, strlen(console_output)); ret = EUCA_OK; } EUCA_FREE(console_append); EUCA_FREE(console_main); EUCA_FREE(console_output); return (ret); }
//! //! //! //! @param[in] log_error //! @param[in] format //! @param[in] ... //! //! @return //! //! @pre //! //! @note //! static char *execlp_output(boolean log_error, ...) { va_list ap; int ntokens = 0; char cmd[256] = ""; // for logging, OK if command gets truncated // run through arguments once to count them va_start(ap, log_error); { char *s; while ((s = va_arg(ap, char *)) != NULL) { ntokens++; } } va_end(ap); if (ntokens < 1) { LOGERROR("internal error: too few arguments to %s\n", __func__); return NULL; } // allocate an array and run through arguments again, copying them into the array char **argv = EUCA_ZALLOC(ntokens + 1, sizeof(char *)); // one extra for the terminating NULL va_start(ap, log_error); { for (int i = 0; i < ntokens; i++) { argv[i] = strdup(va_arg(ap, char *)); // append tokens to 'cmd', strictly for logging purposes int left_in_cmd = sizeof(cmd) - strlen(cmd); if (left_in_cmd > 1) // has room for at least one character and '\0' snprintf(cmd + strlen(cmd), left_in_cmd, "%s%s%s%s", (i > 0) ? (" ") : (""), // add space in front all but the first argument (i == 0 || argv[i][0] == '-') ? ("") : ("'"), // add quoates around non-flags argv[i], (i == 0 || argv[i][0] == '-') ? ("") : ("'")); } } va_end(ap); char *output = NULL; // set up a pipe for getting stdout and stderror from child process int filedes[2]; if (pipe(filedes)) { LOGERROR("failed to create a pipe\n"); goto free; } LOGTRACE("executing: %s\n", cmd); pid_t cpid = fork(); int rc = -1; if (cpid == -1) { LOGERROR("failed to fork\n"); close(filedes[0]); close(filedes[1]); goto free; } else if (cpid == 0) { // child close(filedes[0]); if (dup2(filedes[1], STDOUT_FILENO) == -1) { LOGERROR("failed to dup2\n"); exit(-1); } if (dup2(filedes[1], STDERR_FILENO) == -1) { LOGERROR("failed to dup2\n"); exit(-1); } exit(execvp(argv[0], argv)); } // parent reads stdout and stdin from child into a string close(filedes[1]); int outsize = OUTPUT_ALLOC_CHUNK; // allocate in chunks of this size int nextchar = 0; // offset of the next usable char int bytesread; output = EUCA_ALLOC(outsize, sizeof(char)); if (output) { output[0] = '\0'; // return an empty string if there is no output } while ((output != NULL) && (bytesread = read(filedes[0], output + nextchar, outsize - nextchar - 1)) > 0) { nextchar += bytesread; output[nextchar] = '\0'; if (nextchar + 1 == outsize) { outsize += OUTPUT_ALLOC_CHUNK; if (outsize > MAX_OUTPUT_BYTES) { LOGERROR("internal error: output from command is too long\n"); EUCA_FREE(output); break; } output = EUCA_REALLOC(output, outsize, sizeof(char)); } } if (output == NULL) { LOGERROR("failed to allocate mem for output\n"); } close(filedes[0]); { // wait for the child to reap status int status; rc = waitpid(cpid, &status, 0); if (rc == -1) { LOGERROR("failed to wait for child process\n"); } else if (WIFEXITED(status)) { rc = WEXITSTATUS(status); if (rc) { LOGERROR("child return non-zero status (%d)\n", rc); } } else { LOGERROR("child process did not terminate normally\n"); rc = -1; } } if (rc) { // there were problems above if ((output != NULL) && strstr(cmd, "losetup") && strstr(output, ": No such device or address")) { rc = 0; } else { if (log_error) { LOGERROR("bad return code from cmd %s\n", cmd); LOGDEBUG("%s\n", output); } EUCA_FREE(output); // will be set to NULL } } free: for (int i = 0; i < ntokens; i++) { EUCA_FREE(argv[i]); } EUCA_FREE(argv); return output; }