//! //! Handle the client describe resource 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] resourceType UNUSED //! @param[out] outRes a list of resources we retrieved data for //! //! @return EUCA_OK on success or EUCA_ERROR on failure. //! int ncDescribeResourceStub(ncStub * pStub, ncMetadata * pMeta, char *resourceType, ncResource ** outRes) { int ret = EUCA_OK; ncResource *res = NULL; loadNcStuff(); if (myconfig->res.memorySizeMax <= 0) { // not initialized? res = allocate_resource("OK", "iqn.1993-08.org.debian:01:736a4e92c588", 1024000, 1024000, 30000000, 30000000, 4096, 4096, "none"); if (!res) { LOGERROR("fakeNC: describeResource(): failed to allocate fake resource\n"); ret = EUCA_ERROR; } else { memcpy(&(myconfig->res), res, sizeof(ncResource)); EUCA_FREE(res); } } if (!ret) { res = EUCA_ALLOC(1, sizeof(ncResource)); memcpy(res, &(myconfig->res), sizeof(ncResource)); *outRes = res; } else { *outRes = NULL; } saveNcStuff(); return (ret); }
//! //! appends string 'src' to 'dst', up to 'src_len' characters (unless set //! to 0, in which case to the end of 'src'), enlarging the 'dst' as necessary //! returns the concatenated string or NULL if memory could not be allocated //! if 'src' is an empty string, 'dst' is returned. //! //! @param[in] dst the destination string to append to //! @param[in] src the source string to add to 'dst' //! @param[in] src_limit the number of character to append from 'src' //! //! @return the concatenated string or NULL if memory could not be allocated //! if 'src' is an empty string, 'dst' is returned. //! static char *c_wcappendn(char *dst, const char *src, size_t src_limit) { size_t src_len = 0; size_t dst_len = 0; // Make sure we have a valid source if (src == NULL) return (dst); // Should not be empty if ((src_len = strlen(src)) < 1) return (dst); // Estimate the proper length if ((src_len > src_limit) && (src_limit > 0)) src_len = src_limit; if (dst != NULL) { dst_len = strlen(dst); if ((dst = (char *)EUCA_REALLOC(dst, (dst_len + src_len + 1), sizeof(char))) == NULL) { return (NULL); } } else { if ((dst = (char *)EUCA_ALLOC((dst_len + src_len + 1), sizeof(char))) == NULL) { return (NULL); } *dst = '\0'; } return (strncat(dst, src, src_len)); }
//! //! //! //! @param[in] log_error //! @param[in] format //! @param[in] ... //! //! @return //! //! @pre //! //! @note //! static char *pruntf(boolean log_error, char *format, ...) { va_list ap; FILE *IF = NULL; int rc = -1; int outsize = 1025; char cmd[1024] = { 0 }; size_t bytes = 0; char *output = NULL; va_start(ap, format); vsnprintf(cmd, 1024, format, ap); strncat(cmd, " 2>&1", 1024 - 1); output = NULL; IF = popen(cmd, "r"); if (!IF) { LOGERROR("cannot popen() cmd '%s' for read\n", cmd); va_end(ap); return (NULL); } output = EUCA_ALLOC(outsize, sizeof(char)); if (output) { output[0] = '\0'; // make sure we return an empty string if there is no output } while ((output != NULL) && (bytes = fread(output + (outsize - 1025), 1, 1024, IF)) > 0) { output[(outsize - 1025) + bytes] = '\0'; outsize += 1024; output = EUCA_REALLOC(output, outsize, sizeof(char)); } if (output == NULL) { LOGERROR("failed to allocate mem for output\n"); va_end(ap); pclose(IF); return (NULL); } rc = pclose(IF); if (rc) { //! @TODO improve this hacky special case: failure to find or detach non-existing loop device is not a failure if (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); } } va_end(ap); return (output); }
//! //! read file 'path' into a new string //! //! @param[in] path //! //! @return the string content of the given file //! //! @note the caller must free the memory when done. //! char *file2str(const char *path) { int fp = 0; int bytes = 0; int bytes_total = 0; int to_read = 0; char *p = NULL; char *content = NULL; off_t file_size = 0; struct stat mystat = { 0 }; if (stat(path, &mystat) < 0) { LOGERROR("errno: %d could not stat file %s\n", errno, path); return (content); } file_size = mystat.st_size; if ((content = EUCA_ALLOC((file_size + 1), sizeof(char))) == NULL) { LOGERROR("out of memory reading file %s\n", path); return (content); } if ((fp = open(path, O_RDONLY)) < 0) { LOGERROR("errno: %d failed to open file %s\n", errno, path); EUCA_FREE(content); return (content); } p = content; to_read = (((SSIZE_MAX) < file_size) ? (SSIZE_MAX) : file_size); while ((bytes = read(fp, p, to_read)) > 0) { bytes_total += bytes; p += bytes; if (to_read > (file_size - bytes_total)) { to_read = file_size - bytes_total; } } close(fp); if (bytes < 0) { LOGERROR("failed to read file %s\n", path); EUCA_FREE(content); return (content); } *p = '\0'; return (content); }
//! //! //! //! @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; }
//! //! Remove a directory given by the psPath string pointer. If the 'force' parameter //! is set to TRUE, the directory will be emptied and deleted. If the 'force' //! parameter is set to FALSE then this is the equivalent of an 'rmdir()' system //! calls which will not delete a non-empty directory. //! //! @param[in] psPath a constant pointer to the string containing the path to the directory to remove. //! @param[in] force set to TRUE, will force remove a non-empty directory //! //! @return EUCA_OK on success or the following error code: //! EUCA_INVALID_ERROR if any of our pre-conditions are not met //! EUCA_SYSTEM_ERROR if the system fails to remove a file or directory in the process //! EUCA_MEMORY_ERROR if we fail to allocate memory during the process //! //! @see //! //! @pre \li psPath must not be NULL //! \li psPath must be a valid path to a directory //! \li if force is set to FALSE, the directory should be empty //! //! @post \li on success, the directory will be removed //! \li on failure, the directory may remain with some content //! //! @note //! int euca_rmdir(const char *psPath, boolean force) { int result = EUCA_OK; char *psBuf = NULL; DIR *pDir = NULL; size_t len = 0; size_t pathLen = 0; struct dirent *pDirEnt = NULL; struct stat statbuf = { 0 }; // Make sure we have a path if (psPath == NULL) { return (EUCA_INVALID_ERROR); } // If force was set, read the directory and empty it if (force) { // Retrieve the length of our directory path pathLen = strlen(psPath); // Open the directory and start scanning for items if ((pDir = opendir(psPath)) != NULL) { while ((result == EUCA_OK) && ((pDirEnt = readdir(pDir)) != NULL)) { // Skip the names "." and ".." as we don't want to recurse on them. if (!strcmp(pDirEnt->d_name, ".") || !strcmp(pDirEnt->d_name, "..")) { continue; } len = pathLen + strlen(pDirEnt->d_name) + 2; if ((psBuf = EUCA_ALLOC(len, sizeof(char))) != NULL) { snprintf(psBuf, len, "%s/%s", psPath, pDirEnt->d_name); if (stat(psBuf, &statbuf) == 0) { if (S_ISDIR(statbuf.st_mode)) { result = euca_rmdir(psBuf, TRUE); } else { if (unlink(psBuf) != 0) { result = EUCA_SYSTEM_ERROR; } } } EUCA_FREE(psBuf); } else { // Memory failure result = EUCA_MEMORY_ERROR; } } closedir(pDir); } else { // return the proper error if (errno == ENOTDIR) return (EUCA_INVALID_ERROR); return (EUCA_SYSTEM_ERROR); } } // If we were successful so far, remove the directory if (result == EUCA_OK) { if (rmdir(psPath) != 0) { // Set the proper return error if (errno == ENOTDIR) return (EUCA_INVALID_ERROR); return (EUCA_SYSTEM_ERROR); } } return (result); }
//! //! substitutes in 's' all occurence of variables '${var}' //! based on the 'vars' map (NULL-terminated array of wchar_map * pointers) //! returns a new string with all variables substituted or returns NULL //! (and logs an error with logprintfl()) if some variables were not //! found in the map or if the map is empty //! //! @param[in] s the string containing variables //! @param[in] vars the list of variables //! //! @return a string containing the substitution //! //! @pre The s field must not be NULL //! //! @note caller is responsible to free the returned string //! char *c_varsub(const char *s, const char_map * vars[]) { boolean malformed = FALSE; char *result = NULL; const char *remainder = s; char *var_start = NULL; char *var_end = NULL; char *val = NULL; char *missed_var = NULL; char *vartok = NULL; size_t var_len = 0; size_t pref_len = strlen(C_VAR_PREFIX); size_t suff_len = strlen(C_VAR_SUFFIX); if (s == NULL) { return (NULL); } if (vars == NULL) { return ((char *)strdup(s)); } while ((var_start = strstr(remainder, C_VAR_PREFIX)) != NULL) { // we have a beginning of a variable if (strlen(var_start) <= (pref_len + suff_len)) { // nothing past the prefix malformed = TRUE; break; } if ((var_end = strstr(var_start + pref_len, C_VAR_SUFFIX)) == NULL) { // not suffix after prefix malformed = TRUE; break; } // length of the variable var_len = var_end - var_start - pref_len; if (var_len < 1) { // empty var name remainder = var_end + suff_len; // move the pointer past the empty variable (skip it) malformed = TRUE; continue; } if ((val = c_find_valn(vars, var_start + pref_len, var_len)) == NULL) { if ((missed_var = strndup(var_start + pref_len, var_len)) == NULL) { LOGWARN("failed to substitute variable\n"); continue; } else { LOGWARN("substituted variable: %s%s%s\n", C_VAR_PREFIX, missed_var, C_VAR_SUFFIX); } if ((vartok = (char *)EUCA_ALLOC(1, (strlen(C_VAR_PREFIX) + strlen(C_VAR_SUFFIX) + strlen(missed_var) + 1))) == NULL) { EUCA_FREE(result); EUCA_FREE(missed_var); return (NULL); } sprintf(vartok, "%s%s%s", C_VAR_PREFIX, missed_var, C_VAR_SUFFIX); if (var_start > remainder) { // there is text prior to the variable if ((result = c_wcappendn(result, remainder, var_start - remainder)) == NULL) { //! @todo more specific error LOGERROR("failed to append during variable substitution"); EUCA_FREE(vartok); EUCA_FREE(missed_var); break; } } result = c_wcappendn(result, vartok, 0); remainder = var_end + suff_len; // move the pointer past the empty variable (skip it) EUCA_FREE(missed_var); EUCA_FREE(vartok); continue; } if (var_start > remainder) { // there is text prior to the variable if ((result = c_wcappendn(result, remainder, var_start - remainder)) == NULL) { //! @todo more specific error LOGERROR("failed to append during variable substitution"); break; } } result = c_wcappendn(result, val, 0); remainder = var_end + suff_len; } result = c_wcappendn(result, remainder, 0); if (malformed) { //! @todo print the string LOGWARN("malformed string used for substitution\n"); } return (result); }
//! //! 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 char *xmlFP; if ((xmlFP = EUCA_ALLOC(sizeof(instance->xmlFilePath), sizeof(char))) == NULL) { LOGERROR("out of memory (for temporary string allocation)\n"); goto free; } euca_strncpy(xmlFP, instance->xmlFilePath, sizeof(instance->xmlFilePath)); if (read_instance_xml(xmlFP, instance) != EUCA_OK) { LOGERROR("failed to read instance XML\n"); EUCA_FREE(xmlFP); goto free; } EUCA_FREE(xmlFP); } // 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); // 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); }
//! //! Handles the get keys service request. //! //! @param[in] service service name identifier //! @param[out] outCCCert output CC Certificate //! @param[out] outNCCert output NC certificate //! //! @return EUCA_OK on success or the following error codes: //! \li EUCA_MEMORY_ERROR: if we fail to allocate memory //! \li EUCA_INVALID_ERROR: if any parameter does not meet the preconditions //! //! @pre All parameters must be non-NULLs. //! //! @post On success, the outCCCert, outNCCert parameters are set appropriately. //! int doGetKeys(char *service, char **outCCCert, char **outNCCert) { int fd = -1; int rc = 0; int bufsize = 0; int pid = 0; int filedes[2] = { 0 }; int status = 0; char *tmp = NULL; char *buf = NULL; char *home = NULL; char *ccert = NULL; char *ncert = NULL; char file[MAX_PATH] = { 0 }; axutil_env_t *env = NULL; axis2_char_t *client_home = NULL; axis2_stub_t *stub = NULL; if (!service || !outCCCert || !outNCCert) { printf("ERROR: Invalid params: service=%s, outCCCert=%p, outNCCert=%p\n", service, outCCCert, outNCCert); return (EUCA_INVALID_ERROR); } *outCCCert = *outNCCert = NULL; bufsize = 1000 * 1024; if ((buf = EUCA_ALLOC(bufsize, sizeof(char))) == NULL) { printf("ERROR: Out of memory!\n"); return (EUCA_MEMORY_ERROR); } if (!strcmp(service, "self")) { home = NULL; if ((tmp = getenv("EUCALYPTUS")) != NULL) home = strdup(tmp); if (!home) home = strdup(""); if (!home) { printf("ERROR: Out of memory!\n"); EUCA_FREE(buf); return (EUCA_MEMORY_ERROR); } snprintf(file, MAX_PATH, EUCALYPTUS_KEYS_DIR "/cluster-cert.pem", home); if ((fd = open(file, O_RDONLY)) >= 0) { bzero(buf, bufsize); lseek(fd, -1 * bufsize, SEEK_END); if ((rc = read(fd, buf, bufsize)) > 0) { *outCCCert = base64_enc(((unsigned char *)buf), strlen(buf)); } close(fd); } snprintf(file, MAX_PATH, EUCALYPTUS_KEYS_DIR "/node-cert.pem", home); if ((fd = open(file, O_RDONLY)) >= 0) { bzero(buf, bufsize); lseek(fd, -1 * bufsize, SEEK_END); // make sure that buf is NULL terminated if ((rc = read(fd, buf, bufsize - 1)) > 0) { *outNCCert = base64_enc(((unsigned char *)buf), strlen(buf)); } close(fd); } EUCA_FREE(home); } else { if (pipe(filedes) == 0) { pid = fork(); if (pid == 0) { close(filedes[0]); env = axutil_env_create_all(NULL, 0); if ((client_home = AXIS2_GETENV("AXIS2C_HOME")) == NULL) { printf("ERROR: cannot retrieve AXIS2_HOME environment variable.\n"); exit(1); } else { if ((stub = axis2_stub_create_EucalyptusGL(env, client_home, service)) == NULL) { printf("ERROR: cannot retrieve AXIS2 stub.\n"); exit(1); } ccert = ncert = NULL; if ((rc = gl_getKeys("self", &ccert, &ncert, env, stub)) == EUCA_OK) { bzero(buf, bufsize); if (ccert) snprintf(buf, bufsize, "%s", ccert); rc = write(filedes[1], buf, bufsize); bzero(buf, bufsize); if (ncert) snprintf(buf, bufsize, "%s", ncert); rc = write(filedes[1], buf, bufsize); } } close(filedes[1]); exit(0); } else { close(filedes[1]); rc = read(filedes[0], buf, bufsize - 1); if (rc) { *outCCCert = strdup(buf); } rc = read(filedes[0], buf, bufsize - 1); if (rc) { *outNCCert = strdup(buf); } close(filedes[0]); wait(&status); } } } EUCA_FREE(buf); return (EUCA_OK); }
//! //! Main entry point of the application //! //! @param[in] argc the number of parameter passed on the command line //! @param[in] argv the list of arguments //! //! @return EUCA_OK //! int main(int argc, char **argv) { int rc = 0; int i = 0; int port = 0; int use_wssec = 0; int ccsLen = 0; int resSize = 0; char **ccs = NULL; char *nameserver = NULL; char *euca_home = NULL; char buf[40960] = { 0 }; char configFile[1024] = { 0 }; char policyFile[1024] = { 0 }; char *instIds[256] = { 0 }; char *amiId = NULL; char *amiURL = NULL; char *kernelId = NULL; char *kernelURL = NULL; char *ramdiskId = NULL; char *ramdiskURL = NULL; axutil_env_t *env = NULL; axis2_char_t *client_home = NULL; axis2_char_t endpoint_uri[256] = { 0 }; axis2_char_t *tmpstr = NULL; axis2_stub_t *stub = NULL; virtualMachine params = { 64, 1, 64, "m1.small" }; sensorResource **res; bzero(&mymeta, sizeof(ncMetadata)); mymeta.userId = strdup("admin"); mymeta.correlationId = strdup("1234abcd"); mymeta.epoch = 3; mymeta.servicesLen = 16; snprintf(mymeta.services[15].name, 16, "eucalyptusname"); snprintf(mymeta.services[15].type, 16, "eucalyptustype"); snprintf(mymeta.services[15].partition, 16, "eucalyptuspart"); mymeta.services[15].urisLen = 1; snprintf(mymeta.services[15].uris[0], 512, "http://192.168.254.3:8773/services/Eucalyptus"); if (MODE == 0) { if (argc != 2 || strcmp(argv[1], "-9")) { printf("only runnable from inside euca\n"); exit(1); } } else { if (argc < 3) { printf("USAGE: CCclient <host:port> <command> <opts>\n"); exit(1); } } euca_home = getenv("EUCALYPTUS"); if (!euca_home) { euca_home = ""; } snprintf(configFile, 1024, EUCALYPTUS_CONF_LOCATION, euca_home); snprintf(policyFile, 1024, EUCALYPTUS_KEYS_DIR "/cc-client-policy.xml", euca_home); rc = get_conf_var(configFile, "CC_PORT", &tmpstr); if (rc != 1) { // error logprintf("ERROR: parsing config file (%s) for CC_PORT\n", configFile); exit(1); } else { port = atoi(tmpstr); } rc = get_conf_var(configFile, "ENABLE_WS_SECURITY", &tmpstr); if (rc != 1) { /* Default to enabled */ use_wssec = 1; } else { if (!strcmp(tmpstr, "Y")) { use_wssec = 1; } else { use_wssec = 0; } } if (MODE == 0) { snprintf(endpoint_uri, 256, "http://localhost:%d/axis2/services/EucalyptusCC", port); } else { snprintf(endpoint_uri, 256, "http://%s/axis2/services/EucalyptusCC", argv[1]); } env = axutil_env_create_all("/tmp/fofo", AXIS2_LOG_LEVEL_TRACE); client_home = AXIS2_GETENV("AXIS2C_HOME"); if (!client_home) { printf("must have AXIS2C_HOME set\n"); exit(1); } stub = axis2_stub_create_EucalyptusCC(env, client_home, endpoint_uri); if (use_wssec) { rc = InitWSSEC(env, stub, policyFile); if (rc) { printf("cannot initialize WS-SEC policy (%s)\n", policyFile); exit(1); } } if (MODE == 0) { rc = cc_killallInstances(env, stub); if (rc != 0) { printf("cc_killallInstances() failed\n"); exit(1); } } else { if (!strcmp(argv[2], "runInstances")) { if (argv[3]) amiId = argv[3]; if (argv[4]) amiURL = argv[4]; if (argv[5]) kernelId = argv[5]; if (argv[6]) kernelURL = argv[6]; if (argv[10]) ramdiskId = argv[10]; if (argv[11]) ramdiskURL = argv[11]; rc = cc_runInstances(amiId, amiURL, kernelId, kernelURL, ramdiskId, ramdiskURL, atoi(argv[7]), atoi(argv[8]), argv[9], ¶ms, env, stub); if (rc != 0) { printf("cc_runInstances() failed: in:%s out:%d\n", argv[4], rc); exit(1); } } else if (!strcmp(argv[2], "describeInstances")) { rc = cc_describeInstances(NULL, 0, env, stub); if (rc != 0) { printf("cc_describeInstances() failed\n"); exit(1); } } else if (!strcmp(argv[2], "describeServices")) { rc = cc_describeServices(env, stub); if (rc != 0) { printf("cc_describeServices() failed\n"); exit(1); } } else if (!strcmp(argv[2], "startService")) { rc = cc_startService(env, stub); if (rc != 0) { printf("cc_startService() failed\n"); exit(1); } } else if (!strcmp(argv[2], "stopService")) { rc = cc_stopService(env, stub); if (rc != 0) { printf("cc_stopService() failed\n"); exit(1); } } else if (!strcmp(argv[2], "enableService")) { rc = cc_enableService(env, stub); if (rc != 0) { printf("cc_enableService() failed\n"); exit(1); } } else if (!strcmp(argv[2], "disableService")) { rc = cc_disableService(env, stub); if (rc != 0) { printf("cc_disableService() failed\n"); exit(1); } } else if (!strcmp(argv[2], "shutdownService")) { rc = cc_shutdownService(env, stub); if (rc != 0) { printf("cc_shutdownService() failed\n"); exit(1); } } else if (!strcmp(argv[2], "getConsoleOutput")) { rc = cc_getConsoleOutput(argv[3], env, stub); if (rc != 0) { printf("cc_getConsoleOutput() failed\n"); exit(1); } } else if (!strcmp(argv[2], "rebootInstances")) { if (argv[3] != NULL) { instIds[0] = strdup(argv[3]); } rc = cc_rebootInstances(instIds, 1, env, stub); if (rc != 0) { printf("cc_rebootInstances() failed\n"); exit(1); } } else if (!strcmp(argv[2], "terminateInstances")) { i = 3; while (argv[i] != NULL) { instIds[i - 3] = strdup(argv[i]); i++; } if ((i - 3) > 0) { rc = cc_terminateInstances(instIds, i - 3, env, stub); if (rc != 0) { printf("cc_terminateInstances() failed\n"); exit(1); } } } else if (!strcmp(argv[2], "describeResources")) { rc = cc_describeResources(env, stub); if (rc != 0) { printf("cc_describeResources() failed\n"); exit(1); } } else if (!strcmp(argv[2], "startNetwork")) { ccs = EUCA_ALLOC(32, sizeof(char *)); for (i = 0; i < 32; i++) { if (argv[i + 5]) { ccs[i] = strdup(argv[i + 5]); ccsLen++; } else { i = 33; } } rc = cc_startNetwork(atoi(argv[3]), argv[4], ccs, ccsLen, env, stub); if (rc != 0) { printf("cc_startNetwork() failed\n"); exit(1); } } else if (!strcmp(argv[2], "describeNetworks")) { ccs = EUCA_ALLOC(32, sizeof(char *)); for (i = 0; i < 32; i++) { if (argv[i + 3]) { ccs[i] = strdup(argv[i + 3]); ccsLen++; } else { i = 33; } } nameserver = strdup("1.2.3.4"); rc = cc_describeNetworks(nameserver, ccs, ccsLen, env, stub); if (rc != 0) { printf("cc_describeNetworks() failed\n"); exit(1); } } else if (!strcmp(argv[2], "configureNetwork")) { rc = cc_configureNetwork(argv[3], argv[4], argv[5], atoi(argv[6]), atoi(argv[7]), argv[8], env, stub); if (rc != 0) { printf("cc_configureNetwork() failed\n"); exit(1); } } else if (!strcmp(argv[2], "stopNetwork")) { rc = cc_stopNetwork(atoi(argv[3]), argv[4], env, stub); if (rc != 0) { printf("cc_stopNetwork() failed\n"); exit(1); } } else if (!strcmp(argv[2], "broadcastNetworkInfo")) { rc = cc_broadcastNetworkInfo(argv[3], env, stub); if (rc != 0) { printf("cc_broadcastNetworkInfo() failed\n"); exit(1); } } else if (!strcmp(argv[2], "assignAddress")) { rc = cc_assignAddress(argv[3], argv[4], env, stub); if (rc != 0) { printf("cc_assignAddress() failed\n"); exit(1); } } else if (!strcmp(argv[2], "unassignAddress")) { rc = cc_unassignAddress(argv[3], argv[4], env, stub); if (rc != 0) { printf("cc_unassignAddress() failed\n"); exit(1); } } else if (!strcmp(argv[2], "attachVolume")) { rc = cc_attachVolume(argv[3], argv[4], argv[5], argv[6], env, stub); if (rc != 0) { printf("cc_attachVolume() failed\n"); exit(1); } } else if (!strcmp(argv[2], "detachVolume")) { rc = cc_detachVolume(argv[3], argv[4], argv[5], argv[6], atoi(argv[7]), env, stub); if (rc != 0) { printf("cc_unassignNetwork() failed\n"); exit(1); } } else if (!strcmp(argv[2], "bundleInstance")) { rc = cc_bundleInstance(argv[3], argv[4], argv[5], argv[6], argv[7], env, stub); if (rc != 0) { printf("cc_bundleInstance() failed\n"); exit(1); } } else if (!strcmp(argv[2], "bundleRestartInstance")) { rc = cc_bundleRestartInstance(argv[3], env, stub); if (rc != 0) { printf("cc_bundleRestartInstance() failed\n"); exit(1); } } else if (!strcmp(argv[2], "createImage")) { rc = cc_createImage(argv[3], argv[4], argv[5], env, stub); if (rc != 0) { printf("cc_createImage() failed\n"); exit(1); } } else if (!strcmp(argv[2], "describePublicAddresses")) { rc = cc_describePublicAddresses(env, stub); if (rc != 0) { printf("cc_describePublicAddresses() failed\n"); exit(1); } } else if (!strcmp(argv[2], "killallInstances")) { rc = cc_killallInstances(env, stub); if (rc != 0) { printf("cc_killallInstances() failed\n"); exit(1); } } else if (!strcmp(argv[2], "describeSensors")) { rc = cc_describeSensors(10, 5000, NULL, 0, NULL, 0, &res, &resSize, env, stub); if (rc != 0) { printf("cc_describeSensors() failed: error=%d\n", rc); exit(1); } sensor_res2str(buf, sizeof(buf), res, resSize); printf("resources: %d\n%s\n", resSize, buf); } else if (!strcmp(argv[2], "modifyNode")) { rc = cc_modifyNode(argv[3], argv[4], env, stub); if (rc != 0) { printf("cc_modifyNode() failed: error=%d\n", rc); exit(1); } } else if (!strcmp(argv[2], "migrateInstances")) { rc = cc_migrateInstances(argv[3], env, stub); if (rc != 0) { printf("cc_migrateInstances() failed: error=%d\n", rc); exit(1); } } else if (!strcmp(argv[2], "startInstance")) { rc = cc_startInstance(argv[3], env, stub); if (rc != 0) { printf("cc_migrateInstances() failed: error=%d\n", rc); exit(1); } } else if (!strcmp(argv[2], "stopInstance")) { rc = cc_stopInstance(argv[3], env, stub); if (rc != 0) { printf("cc_migrateInstances() failed: error=%d\n", rc); exit(1); } } else { printf("unrecognized operation '%s'\n", argv[2]); exit(1); } } return (EUCA_OK); }
//! //! //! //! @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; }