// checks whether disk state of the item matches the spec (when it does not, function returns 1) int verify_disk_item (const disk_item * di, artifacts_spec * spec) { int ret = ERROR; struct stat mystat; if (stat (di->path, &mystat)<0) return ERROR; if (di->content_size != mystat.st_size) return ERROR; // TODO: check the checksum? char * file_summary = file2str (di->summ); char * spec_summary = gen_summary (spec); if (file_summary==NULL) { logprintfl (EUCAWARN, "warning: failed to read summary file '%s'\n", di->summ); if(spec_summary != NULL) free(spec_summary); ret = OK; } else { if (spec_summary!=NULL) { if (strcmp (file_summary, spec_summary)==0) ret = OK; free (spec_summary); } free (file_summary); } return ret; }
static char * __build_xen_xml_from_template() { char * tmpl = file2str("./vmfiles/txen.xml"); if (tmpl == NULL) { logerror("file2str failed\n"); return NULL; } char * xml = malloc(strlen(tmpl) + 1024); if (xml == NULL) { logerror("malloc failed\n"); return NULL; } #define LUOYUN_INSTANCE_DISK_FILE "/home/dongwu/luoyun/luoyun-cloud/test/vmfiles/os.img" #define LUOYUN_INSTANCE_KERNEL_FILE "/home/dongwu/luoyun/luoyun-cloud/test/vmfiles/kernel" #define LUOYUN_INSTANCE_INITRD_FILE "/home/dongwu/luoyun/luoyun-cloud/test/vmfiles/initrd" sprintf(xml, tmpl, "12", g_xenvmname, LUOYUN_INSTANCE_KERNEL_FILE, LUOYUN_INSTANCE_INITRD_FILE, "256000", "1", LUOYUN_INSTANCE_DISK_FILE, "aa:bb:cc:dd:ee:ff"); free(tmpl); return xml; }
int http_stats(const char *url) { char *buf, *s; char **cur; char *secrets[] = { "os_server", "stats_server", "http_passwd", NULL }; char *files[] = { "/proc/version", "/proc/meminfo", "/proc/cpuinfo", "/proc/interrupts", "/proc/net/dev", "/proc/net/pppoe", "/proc/net/snmp", NULL }; char *contents; if (!(buf = safe_malloc(NVRAMSPACE))) return errno; /* * Get NVRAM variables */ nvram_getall(buf, NVRAMSPACE); for (s = buf; *s; s++) { for (cur = secrets; *cur; cur++) { if (!strncmp(s, *cur, strlen(*cur))) { s += strlen(*cur) + 1; while (*s) *s++ = '*'; break; } } *(s += strlen(s)) = '&'; } /* * Dump interesting /proc entries */ for (cur = files; *cur; cur++) { if ((contents = file2str(*cur))) { s += snprintf(s, buf + BUFSPACE - s, "%s=%s&", *cur, contents); free(contents); } } /* * Report uptime */ s += snprintf(s, buf + BUFSPACE - s, "uptime=%lu&", (unsigned long)time(NULL)); /* * Save */ s += snprintf(s, buf + BUFSPACE - s, "action=save"); buf[BUFSPACE - 1] = '\0'; /* * Post to server */ http_post(url ? : nvram_safe_get("stats_server"), buf, BUFSPACE); free(buf); return 0; }
int main (int argc, char *argv[]) { setprogname (argv[0]); if (argc != 2 && argc !=3) usage (); str s = file2str (argv[1]); int off = -1; if (argc == 3 && !convertint (argv[2], &off)) usage (); if (!s) fatal << "cannot open file: " << argv[1]; const char *cp = strstr (s.cstr (), "\r\n\r\n"); if (!cp) fatal << "file is not a raw HTTP dump: " << argv[1]; cp += 4; size_t sz; Bytef outbuf[100000]; uLong outlen = 100000; int rc = -1; u_int i = 0; Bytef b2[100000]; Bytef *bp = b2; u_int t = 0; while ((sz = getsize (&cp)) > 0) { /* for (i = 0; i < sz && rc < 0; i++) { for (j = sz; j >= 0 && rc < 0; j--) { rc = uncompress (outbuf, &outlen, reinterpret_cast<const Bytef *> (cp+i), j); warn ("%d,%d,%d,%x,%x\n", i, j, rc, char (cp[i]), char (cp[i+1])); } } */ memcpy (bp, cp, sz); bp += sz; t += sz; cp += (2 + sz); } rc = myunc (outbuf, &outlen, reinterpret_cast<const Bytef *> (b2+10), t - 10); if (rc < 0) fatal << "uncompress failed: " << rc << "\n"; warn << "eureka!!! " << i << "\n"; if (write (1, outbuf, outlen) < int (outlen)) fatal << "short write.\n"; exit (0); }
/** * Takes our latest IP table virtual content and puts it into a file in IP tables format that * will be passed to ip_system_restore(). Once completed, the system IP tables should contain * the latest changes we made. * * @param pIpt [in] pointer to the IP table handler structure * * @return 0 on success or any other value if any failure occurred * * @see ipt_system_restore() * * @pre * - Our given pointers must not be NULL * - The IP table structure must have been intialized * - The system must allow us to write to the file configured in the IP table structure * * @post * On success, the system IP tables will contain what we put in our structure. On failure, the * system IP tables should remain unchanged. * * @note */ int ipt_handler_deploy(ipt_handler * pIpt) { int i = 0; int j = 0; int k = 0; char *psPreload = NULL; FILE *pFh = NULL; if (!pIpt || !pIpt->init) { return (1); } ipt_handler_update_refcounts(pIpt); if ((pFh = fopen(pIpt->ipt_file, "w")) == NULL) { LOGERROR("could not open file for write '%s': check permissions\n", pIpt->ipt_file); return (1); } // do the preload stuff first if needed if (strlen(pIpt->preloadPath)) { if ((psPreload = file2str(pIpt->preloadPath)) == NULL) { LOGTRACE("Fail to load IP table preload content from '%s'.\n", pIpt->preloadPath); } else { fprintf(pFh, "%s\n", psPreload); EUCA_FREE(psPreload); } } for (i = 0; i < pIpt->max_tables; i++) { fprintf(pFh, "*%s\n", pIpt->tables[i].name); for (j = 0; j < pIpt->tables[i].max_chains; j++) { if (!pIpt->tables[i].chains[j].flushed && pIpt->tables[i].chains[j].ref_count) { fprintf(pFh, ":%s %s %s\n", pIpt->tables[i].chains[j].name, pIpt->tables[i].chains[j].policyname, pIpt->tables[i].chains[j].counters); } } for (j = 0; j < pIpt->tables[i].max_chains; j++) { if (!pIpt->tables[i].chains[j].flushed && pIpt->tables[i].chains[j].ref_count) { // qsort! qsort(pIpt->tables[i].chains[j].rules, pIpt->tables[i].chains[j].max_rules, sizeof(ipt_rule), ipt_ruleordercmp); for (k = 0; k < pIpt->tables[i].chains[j].max_rules; k++) { if (!pIpt->tables[i].chains[j].rules[k].flushed) { fprintf(pFh, "%s %s\n", pIpt->tables[i].chains[j].rules[k].counterstr, pIpt->tables[i].chains[j].rules[k].iptrule); } } } } fprintf(pFh, "COMMIT\n"); } fclose(pFh); return (ipt_system_restore(pIpt)); }
//! //! //! //! @param[in] path //! @param[in] limit //! //! @return the result of teh file2str() call //! //! @see file2str() //! //! @note the caller must free the memory when done. //! char *file2strn(const char *path, const ssize_t limit) { struct stat mystat = { 0 }; if (stat(path, &mystat) < 0) { LOGERROR("could not stat file %s\n", path); return (NULL); } if (mystat.st_size > limit) { LOGERROR("file %s exceeds the limit (%lu) in file2strn()\n", path, limit); return (NULL); } return (file2str(path)); }
static char * __build_kvm_xml_from_template() { char * tmpl = file2str("./vmfiles/tkvm.xml"); if (tmpl == NULL) { logerror("file2str failed\n"); return NULL; } char * xml = malloc(strlen(tmpl) + 1024); if (xml == NULL) { logerror("malloc failed\n"); return NULL; } #define LUOYUN_INSTANCE_KVM_DISK_FILE "/home/dongwu/luoyun-cloud/test/vmfiles/os.img" sprintf(xml, tmpl, "12", g_kvmvmname, "512000", "1", LUOYUN_INSTANCE_KVM_DISK_FILE, "aa:bb:cc:dd:ee:ff"); free(tmpl); return xml; }
bool get_srp_params (ptr<aclnt> c, bigint *Np, bigint *gp) { bool valid = false; bigint N,g; str srpfile, parms; if ((srpfile = sfsconst_etcfile ("sfs_srp_parms")) && (parms = file2str (srpfile)) && import_srp_params (parms, &N, &g) ) { if (!srp_base::checkparam (N, g)) { warn << "Invalid SRP parameters read from file: " << srpfile << "\n"; } else valid = true; } if (!valid && c) { sfsauth2_query_arg aqa; sfsauth2_query_res aqr; aqa.type = SFSAUTH_SRPPARMS; aqa.key.set_type (SFSAUTH_DBKEY_NULL); clnt_stat err = c->scall (SFSAUTH2_QUERY, &aqa, &aqr); if (!err && aqr.type == SFSAUTH_SRPPARMS && import_srp_params (aqr.srpparms->parms, &N, &g)) { if (!srp_base::checkparam (N, g)) { warn << "Invalid SRP parameters read from sfsauthd.\n"; return false; } else { valid = true; } } } if (valid) { *Np = N; *gp = g; return true; } return false; }
static pid_t get_lpad_pid(pid_t pid) { static pid_t lpad_pid = UNKNOWN_PID; static const char lpad_path[] = DEBUG_LAUNCH_PRELOAD_PATH; enum { lpad_path_len = sizeof(lpad_path) }; if (lpad_pid == UNKNOWN_PID) { char fname[64]; char buf[lpad_path_len]; snprintf(fname, sizeof(fname), "/proc/%d/cmdline", pid); if (-1 == file2str(fname, buf, lpad_path_len)) return lpad_pid; buf[lpad_path_len - 1] = '\0'; if (strncmp(buf, lpad_path, lpad_path_len - 1) == 0) lpad_pid = pid; } return lpad_pid; }
Boolean get_proc(peg_proc_t* P, int &pIndex , Boolean find_by_pid) { static struct dirent *dir; static struct stat stat_buff; static char path[32]; static char buffer[512]; int allocated = 0; DIR* procDir; int count; pthread_mutex_lock( &proc_mutex ); count = 0; if( ! (procDir = opendir("/proc"))) { pthread_mutex_unlock( &proc_mutex ); return false; } // get rid of any .ZZZ files while ((dir = readdir(procDir)) && (*dir->d_name < '0' || *dir->d_name > '9')) ; do { if (dir == 0 ) break; // make sure we get only dirs that start with [0-9] if (*dir->d_name < '0' || *dir->d_name > '9') { continue; } if ( find_by_pid ) { if ( atoi( dir->d_name ) == pIndex ) break; } else { if ( count == pIndex ) break; } count++; } while ( (dir = readdir(procDir)) ); if (!dir || !dir->d_name) // then we've finished lookin at all the procs { if (procDir) closedir(procDir); pthread_mutex_unlock( &proc_mutex ); return false; } // we now have the right processId and proc table entry sprintf(path, "/proc/%s", dir->d_name); if (stat(path, &stat_buff) == -1) // our process stopped running { if (procDir) closedir(procDir); pthread_mutex_unlock( &proc_mutex ); return false; } if ((file2str(path, "stat", buffer, sizeof buffer)) == -1) { if (procDir) closedir(procDir); pthread_mutex_unlock( &proc_mutex ); return false; } if( ! parseProcStat(buffer, P) ) { if (procDir) closedir(procDir); pthread_mutex_unlock( &proc_mutex ); return false; } if ((file2str(path, "statm", buffer, sizeof buffer)) != -1 ) parseProcStatm(buffer, P); if ((file2str(path, "status", buffer, sizeof buffer)) != -1 ) parseProcStatus(buffer, P); if ((file2str(path, "cmdline", buffer, sizeof buffer)) != -1) { P->pst_cmd.assign(buffer); } else { P->pst_cmd.assign(P->pst_ucomm); } sprintf(path, "/proc/"); if ((file2str(path, "uptime", buffer, sizeof buffer)) != -1) { doPercentCPU(buffer,P); } else P->pst_pctcpu = 0; if (procDir) closedir(procDir); pIndex = count; // set pIndex to the next "reference" pthread_mutex_unlock( &proc_mutex ); return true; }
void start_nas_notify(char *ifname) { char *argv[] = { "nas4not", "lan", ifname, "up", NULL, /* role */ NULL, /* crypto */ NULL, /* auth */ NULL, /* passphrase */ NULL, /* ssid */ NULL }; char *str = NULL; char tmp[100], prefix[] = "wlXXXXXXXXXX_", pidfile[] = "/tmp/nas.wlXXXXXXXlan.pid"; int unit; char remote[ETHER_ADDR_LEN]; char ssid[48], pass[80], auth[16], crypto[16], role[8]; int i; /* * the wireless interface must be configured to run NAS */ wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit)); snprintf(prefix, sizeof(prefix), "wl%d_", unit); snprintf(pidfile, sizeof(pidfile), "/tmp/nas.wl%dlan.pid", unit); if (!(str = file2str(pidfile))) // no pidfile means no nas was run (required) { return; } free(str); sleep(3); /* * find WDS link configuration */ wl_ioctl(ifname, WLC_WDS_GET_REMOTE_HWADDR, remote, ETHER_ADDR_LEN); for (i = 0; i < MAX_NVPARSE; i++) { char mac[ETHER_ADDR_STR_LEN]; uint8 ea[ETHER_ADDR_LEN]; if (get_wds_wsec(unit, i, mac, role, crypto, auth, ssid, pass) && ether_atoe(mac, ea) && !bcmp(ea, remote, ETHER_ADDR_LEN)) { argv[4] = role; argv[5] = crypto; argv[6] = auth; argv[7] = pass; argv[8] = ssid; break; } } /* * did not find WDS link configuration, use wireless' */ if (i == MAX_NVPARSE) { /* * role */ argv[4] = "auto"; /* * crypto */ argv[5] = nvram_safe_get(strcat_r(prefix, "crypto", tmp)); /* * auth mode */ argv[6] = nvram_safe_get(strcat_r(prefix, "akm", tmp)); /* * passphrase */ argv[7] = nvram_safe_get(strcat_r(prefix, "wpa_psk", tmp)); /* * ssid */ argv[8] = nvram_safe_get(strcat_r(prefix, "ssid", tmp)); } int pid; _evalpid(argv, ">/dev/console", 0, &pid); }
//! //! Defines the thread that does the actual reboot of an instance. //! //! @param[in] arg a transparent pointer to the argument passed to this thread handler //! //! @return Always return NULL //! static void *rebooting_thread(void *arg) { #define REATTACH_RETRIES 3 int i = 0; int err = 0; int error = 0; int rc = 0; int log_level_for_devstring = EUCATRACE; char *xml = NULL; char *remoteDevStr = NULL; char path[MAX_PATH] = ""; char lpath[MAX_PATH] = ""; char resourceName[1][MAX_SENSOR_NAME_LEN] = { {0} }; char resourceAlias[1][MAX_SENSOR_NAME_LEN] = { {0} }; ncVolume *volume = NULL; ncInstance *instance = ((ncInstance *) arg); virDomainPtr dom = NULL; virConnectPtr *conn = NULL; logprintfl(EUCADEBUG, "[%s] spawning rebooting thread\n", instance->instanceId); if ((xml = file2str(instance->libvirtFilePath)) == NULL) { logprintfl(EUCAERROR, "[%s] cannot obtain instance XML file %s\n", instance->instanceId, instance->libvirtFilePath); return NULL; } if ((conn = check_hypervisor_conn()) == NULL) { logprintfl(EUCAERROR, "[%s] cannot restart instance %s, abandoning it\n", instance->instanceId, instance->instanceId); change_state(instance, SHUTOFF); EUCA_FREE(xml); return NULL; } sem_p(hyp_sem); { dom = virDomainLookupByName(*conn, instance->instanceId); } sem_v(hyp_sem); if (dom == NULL) { EUCA_FREE(xml); return NULL; } sem_p(hyp_sem); { // for KVM, must stop and restart the instance logprintfl(EUCADEBUG, "[%s] destroying domain\n", instance->instanceId); error = virDomainDestroy(dom); // @todo change to Shutdown? is this synchronous? virDomainFree(dom); } sem_v(hyp_sem); if (error) { EUCA_FREE(xml); return NULL; } // Add a shift to values of three of the metrics: ones that // drop back to zero after a reboot. The shift, which is based // on the latest value, ensures that values sent upstream do // not go backwards . sensor_shift_metric(instance->instanceId, "CPUUtilization"); sensor_shift_metric(instance->instanceId, "NetworkIn"); sensor_shift_metric(instance->instanceId, "NetworkOut"); // domain is now shut down, create a new one with the same XML sem_p(hyp_sem); { logprintfl(EUCAINFO, "[%s] rebooting\n", instance->instanceId); dom = virDomainCreateLinux(*conn, xml, 0); } sem_v(hyp_sem); EUCA_FREE(xml); euca_strncpy(resourceName[0], instance->instanceId, MAX_SENSOR_NAME_LEN); sensor_refresh_resources(resourceName, resourceAlias, 1); // refresh stats so we set base value accurately // re-attach each volume previously attached for (i = 0; i < EUCA_MAX_VOLUMES; ++i) { volume = &instance->volumes[i]; if (strcmp(volume->stateName, VOL_STATE_ATTACHED) && strcmp(volume->stateName, VOL_STATE_ATTACHING)) continue; // skip the entry unless attached or attaching logprintfl(EUCADEBUG, "[%s] volumes [%d] = '%s'\n", instance->instanceId, i, volume->stateName); // get credentials, decrypt them remoteDevStr = get_iscsi_target(volume->remoteDev); if (!remoteDevStr || !strstr(remoteDevStr, "/dev")) { logprintfl(EUCAERROR, "[%s] failed to get local name of host iscsi device when re-attaching\n", instance->instanceId); rc = 1; } else { // set the path snprintf(path, sizeof(path), EUCALYPTUS_VOLUME_XML_PATH_FORMAT, instance->instancePath, volume->volumeId); // vol-XXX.xml snprintf(lpath, sizeof(lpath), EUCALYPTUS_VOLUME_LIBVIRT_XML_PATH_FORMAT, instance->instancePath, volume->volumeId); // vol-XXX-libvirt.xml // read in libvirt XML, which may have been modified by the hook above if ((xml = file2str(lpath)) == NULL) { logprintfl(EUCAERROR, "[%s][%s] failed to read volume XML from %s\n", instance->instanceId, volume->volumeId, lpath); rc = 1; } } EUCA_FREE(remoteDevStr); if (!rc) { // zhill - wrap with retry in case libvirt is dumb. err = 0; for (i = 1; i < REATTACH_RETRIES; i++) { // protect libvirt calls because we've seen problems during concurrent libvirt invocations sem_p(hyp_sem); { err = virDomainAttachDevice(dom, xml); } sem_v(hyp_sem); if (err) { logprintfl(EUCAERROR, "[%s][%s] failed to reattach volume (attempt %d of %d)\n", instance->instanceId, volume->volumeId, i, REATTACH_RETRIES); logprintfl(EUCADEBUG, "[%s][%s] error from virDomainAttachDevice: %d xml: %s\n", instance->instanceId, volume->volumeId, err, xml); sleep(3); // sleep a bit and retry } else { logprintfl(EUCAINFO, "[%s][%s] volume reattached as '%s'\n", instance->instanceId, volume->volumeId, volume->localDevReal); break; } } log_level_for_devstring = EUCATRACE; if (err) log_level_for_devstring = EUCADEBUG; logprintfl(log_level_for_devstring, "[%s][%s] remote device string: %s\n", instance->instanceId, volume->volumeId, volume->remoteDev); } EUCA_FREE(xml); } if (dom == NULL) { logprintfl(EUCAERROR, "[%s] failed to restart instance\n", instance->instanceId); change_state(instance, SHUTOFF); return NULL; } sem_p(hyp_sem); { virDomainFree(dom); } sem_v(hyp_sem); return NULL; #undef REATTACH_RETRIES }
//! //! Handles the instance migration request. //! //! @param[in] nc a pointer to the node controller (NC) state //! @param[in] pMeta a pointer to the node controller (NC) metadata structure //! @param[in] instances metadata for the instance to migrate to destination //! @param[in] instancesLen number of instances in the instance list //! @param[in] action IP of the destination Node Controller //! @param[in] credentials credentials that enable the migration //! //! @return EUCA_OK on success or EUCA_*ERROR on failure //! //! @pre //! //! @post static int doMigrateInstances(struct nc_state_t *nc, ncMetadata * pMeta, ncInstance ** instances, int instancesLen, char *action, char *credentials) { int ret = EUCA_OK; int credentials_prepared = 0; if (instancesLen <= 0) { LOGERROR("called with invalid instancesLen (%d)\n", instancesLen); pMeta->replyString = strdup("internal error (invalid instancesLen)"); return (EUCA_INVALID_ERROR); } LOGDEBUG("verifying %d instance[s] for migration...\n", instancesLen); for (int inst_idx = 0; inst_idx < instancesLen; inst_idx++) { LOGDEBUG("verifying instance # %d...\n", inst_idx); if (instances[inst_idx]) { ncInstance *instance_idx = instances[inst_idx]; LOGDEBUG("[%s] proposed migration action '%s' (%s > %s) [creds=%s]\n", SP(instance_idx->instanceId), SP(action), SP(instance_idx->migration_src), SP(instance_idx->migration_dst), (instance_idx->migration_credentials == NULL) ? "UNSET" : "present"); } else { pMeta->replyString = strdup("internal error (instance count mismatch)"); LOGERROR("Mismatch between migration instance count (%d) and length of instance list\n", instancesLen); return (EUCA_ERROR); } } // TO-DO: Optimize the location of this loop, placing it inside various conditionals below? for (int inst_idx = 0; inst_idx < instancesLen; inst_idx++) { ncInstance *instance_req = instances[inst_idx]; char *sourceNodeName = instance_req->migration_src; char *destNodeName = instance_req->migration_dst; LOGDEBUG("[%s] processing instance # %d (%s > %s)\n", instance_req->instanceId, inst_idx, instance_req->migration_src, instance_req->migration_dst); // this is a call to the source of migration if (!strcmp(pMeta->nodeName, sourceNodeName)) { // locate the instance structure ncInstance *instance; sem_p(inst_sem); { instance = find_instance(&global_instances, instance_req->instanceId); } sem_v(inst_sem); if (instance == NULL) { LOGERROR("[%s] cannot find instance\n", instance_req->instanceId); pMeta->replyString = strdup("failed to locate instance to migrate"); return (EUCA_NOT_FOUND_ERROR); } if (strcmp(action, "prepare") == 0) { sem_p(inst_sem); instance->migration_state = MIGRATION_PREPARING; euca_strncpy(instance->migration_src, sourceNodeName, HOSTNAME_SIZE); euca_strncpy(instance->migration_dst, destNodeName, HOSTNAME_SIZE); euca_strncpy(instance->migration_credentials, credentials, CREDENTIAL_SIZE); instance->migrationTime = time(NULL); save_instance_struct(instance); copy_instances(); sem_v(inst_sem); // Establish migration-credential keys if this is the first instance preparation for this host. LOGINFO("[%s] migration source preparing %s > %s [creds=%s]\n", SP(instance->instanceId), SP(instance->migration_src), SP(instance->migration_dst), (instance->migration_credentials == NULL) ? "UNSET" : "present"); if (!credentials_prepared) { if (generate_migration_keys(sourceNodeName, credentials, TRUE, instance) != EUCA_OK) { pMeta->replyString = strdup("internal error (migration credentials generation failed)"); return (EUCA_SYSTEM_ERROR); } else { credentials_prepared++; } } sem_p(inst_sem); instance->migration_state = MIGRATION_READY; save_instance_struct(instance); copy_instances(); sem_v(inst_sem); } else if (strcmp(action, "commit") == 0) { sem_p(inst_sem); if (instance->migration_state == MIGRATION_IN_PROGRESS) { LOGWARN("[%s] duplicate request to migration source to initiate %s > %s (already migrating)\n", instance->instanceId, instance->migration_src, instance->migration_dst); sem_v(inst_sem); return (EUCA_DUPLICATE_ERROR); } else if (instance->migration_state != MIGRATION_READY) { LOGERROR("[%s] request to commit migration %s > %s when source migration_state='%s' (not 'ready')\n", instance->instanceId, SP(sourceNodeName), SP(destNodeName), migration_state_names[instance->migration_state]); sem_v(inst_sem); return (EUCA_UNSUPPORTED_ERROR); } instance->migration_state = MIGRATION_IN_PROGRESS; outgoing_migrations_in_progress++; LOGINFO("[%s] migration source initiating %s > %s [creds=%s] (1 of %d active outgoing migrations)\n", instance->instanceId, instance->migration_src, instance->migration_dst, (instance->migration_credentials == NULL) ? "UNSET" : "present", outgoing_migrations_in_progress); save_instance_struct(instance); copy_instances(); sem_v(inst_sem); // since migration may take a while, we do them in a thread pthread_t tcb = { 0 }; if (pthread_create(&tcb, NULL, migrating_thread, (void *)instance)) { LOGERROR("[%s] failed to spawn a migration thread\n", instance->instanceId); return (EUCA_THREAD_ERROR); } set_corrid_pthread( get_corrid()!=NULL ? get_corrid()->correlation_id : NULL , tcb); if (pthread_detach(tcb)) { LOGERROR("[%s] failed to detach the migration thread\n", instance->instanceId); return (EUCA_THREAD_ERROR); } } else if (strcmp(action, "rollback") == 0) { if ((instance->migration_state == MIGRATION_READY) || (instance->migration_state == MIGRATION_PREPARING)) { LOGINFO("[%s] rolling back migration (%s > %s) on source\n", instance->instanceId, instance->migration_src, instance->migration_dst); sem_p(inst_sem); migration_rollback(instance); sem_v(inst_sem); } else { LOGINFO("[%s] ignoring request to roll back migration on source with instance in state %s(%s) -- duplicate rollback request?\n", instance->instanceId, instance->stateName, migration_state_names[instance->migration_state]); } } else { LOGERROR("[%s] action '%s' is not valid\n", instance->instanceId, action); return (EUCA_INVALID_ERROR); } } else if (!strcmp(pMeta->nodeName, destNodeName)) { // this is a migrate request to destination if (!strcmp(action, "commit")) { LOGERROR("[%s] action '%s' for migration (%s > %s) is not valid on destination node\n", instance_req->instanceId, action, SP(sourceNodeName), SP(destNodeName)); return (EUCA_UNSUPPORTED_ERROR); } else if (!strcmp(action, "rollback")) { LOGINFO("[%s] rolling back migration (%s > %s) on destination\n", instance_req->instanceId, SP(sourceNodeName), SP(destNodeName)); sem_p(inst_sem); { ncInstance *instance = find_instance(&global_instances, instance_req->instanceId); if (instance != NULL) { LOGDEBUG("[%s] marked for cleanup\n", instance->instanceId); change_state(instance, SHUTOFF); instance->migration_state = MIGRATION_CLEANING; save_instance_struct(instance); } } sem_v(inst_sem); return EUCA_OK; } else if (strcmp(action, "prepare") != 0) { LOGERROR("[%s] action '%s' is not valid or not implemented\n", instance_req->instanceId, action); return (EUCA_INVALID_ERROR); } // Everything from here on is specific to "prepare" on a destination. // allocate a new instance struct ncInstance *instance = clone_instance(instance_req); if (instance == NULL) { LOGERROR("[%s] could not allocate instance struct\n", instance_req->instanceId); goto failed_dest; } sem_p(inst_sem); instance->migration_state = MIGRATION_PREPARING; euca_strncpy(instance->migration_src, sourceNodeName, HOSTNAME_SIZE); euca_strncpy(instance->migration_dst, destNodeName, HOSTNAME_SIZE); euca_strncpy(instance->migration_credentials, credentials, CREDENTIAL_SIZE); save_instance_struct(instance); sem_v(inst_sem); // Establish migration-credential keys. LOGINFO("[%s] migration destination preparing %s > %s [creds=%s]\n", instance->instanceId, SP(instance->migration_src), SP(instance->migration_dst), (instance->migration_credentials == NULL) ? "UNSET" : "present"); // First, call config-file modification script to authorize source node. LOGDEBUG("[%s] authorizing migration source node %s\n", instance->instanceId, instance->migration_src); if (authorize_migration_keys("-a", instance->migration_src, instance->migration_credentials, instance, TRUE) != EUCA_OK) { goto failed_dest; } // Then, generate keys and restart libvirtd. if (generate_migration_keys(instance->migration_dst, instance->migration_credentials, TRUE, instance) != EUCA_OK) { goto failed_dest; } int error; if (vbr_parse(&(instance->params), pMeta) != EUCA_OK) { goto failed_dest; } // set up networking char *brname = NULL; if ((error = vnetStartNetwork(nc->vnetconfig, instance->ncnet.vlan, NULL, NULL, NULL, &brname)) != EUCA_OK) { LOGERROR("[%s] start network failed for instance, terminating it\n", instance->instanceId); EUCA_FREE(brname); goto failed_dest; } euca_strncpy(instance->params.guestNicDeviceName, brname, sizeof(instance->params.guestNicDeviceName)); EUCA_FREE(brname); // TODO: move stuff in startup_thread() into a function? set_instance_params(instance); if ((error = create_instance_backing(instance, TRUE)) // create files that back the disks || (error = gen_instance_xml(instance)) // create euca-specific instance XML file || (error = gen_libvirt_instance_xml(instance))) { // transform euca-specific XML into libvirt XML LOGERROR("[%s] failed to prepare images for migrating instance (error=%d)\n", instance->instanceId, error); goto failed_dest; } // attach any volumes for (int v = 0; v < EUCA_MAX_VOLUMES; v++) { ncVolume *volume = &instance->volumes[v]; if (strcmp(volume->stateName, VOL_STATE_ATTACHED) && strcmp(volume->stateName, VOL_STATE_ATTACHING)) continue; // skip the entry unless attached or attaching LOGDEBUG("[%s] volumes [%d] = '%s'\n", instance->instanceId, v, volume->stateName); // TODO: factor what the following out of here and doAttachVolume() in handlers_default.c int have_remote_device = 0; char *xml = NULL; char *remoteDevStr = NULL; char scUrl[512]; char localDevReal[32], localDevTag[256], remoteDevReal[132]; char *tagBuf = localDevTag; ebs_volume_data *vol_data = NULL; ret = convert_dev_names(volume->localDev, localDevReal, tagBuf); if (ret) goto unroll; //Do the ebs connect. LOGTRACE("[%s][%s] Connecting EBS volume to local host\n", instance->instanceId, volume->volumeId); get_service_url("storage", nc, scUrl); if (strlen(scUrl) == 0) { LOGERROR("[%s][%s] Failed to lookup enabled Storage Controller. Cannot attach volume %s\n", instance->instanceId, volume->volumeId, scUrl); have_remote_device = 0; goto unroll; } else { LOGTRACE("[%s][%s] Using SC URL: %s\n", instance->instanceId, volume->volumeId, scUrl); } //Do the ebs connect. LOGTRACE("[%s][%s] Connecting EBS volume to local host\n", instance->instanceId, volume->volumeId); int rc = connect_ebs_volume(scUrl, volume->attachmentToken, nc->config_use_ws_sec, nc->config_sc_policy_file, nc->ip, nc->iqn, &remoteDevStr, &vol_data); if (rc) { LOGERROR("Error connecting ebs volume %s\n", volume->attachmentToken); have_remote_device = 0; ret = EUCA_ERROR; goto unroll; } // update the volume struct with connection string obtained from SC euca_strncpy(volume->connectionString, vol_data->connect_string, sizeof(volume->connectionString)); if (!remoteDevStr || !strstr(remoteDevStr, "/dev")) { LOGERROR("[%s][%s] failed to connect to iscsi target\n", instance->instanceId, volume->volumeId); remoteDevReal[0] = '\0'; } else { LOGDEBUG("[%s][%s] attached iSCSI target of host device '%s'\n", instance->instanceId, volume->volumeId, remoteDevStr); snprintf(remoteDevReal, sizeof(remoteDevReal), "%s", remoteDevStr); have_remote_device = 1; } EUCA_FREE(remoteDevStr); // something went wrong above, abort if (!have_remote_device) { goto unroll; } // make sure there is a block device if (check_block(remoteDevReal)) { LOGERROR("[%s][%s] cannot verify that host device '%s' is available for hypervisor attach\n", instance->instanceId, volume->volumeId, remoteDevReal); goto unroll; } // generate XML for libvirt attachment request if (gen_volume_xml(volume->volumeId, instance, localDevReal, remoteDevReal) // creates vol-XXX.xml || gen_libvirt_volume_xml(volume->volumeId, instance)) { // creates vol-XXX-libvirt.xml via XSLT transform LOGERROR("[%s][%s] could not produce attach device xml\n", instance->instanceId, volume->volumeId); goto unroll; } // invoke hooks char path[EUCA_MAX_PATH]; char lpath[EUCA_MAX_PATH]; snprintf(path, sizeof(path), EUCALYPTUS_VOLUME_XML_PATH_FORMAT, instance->instancePath, volume->volumeId); // vol-XXX.xml snprintf(lpath, sizeof(lpath), EUCALYPTUS_VOLUME_LIBVIRT_XML_PATH_FORMAT, instance->instancePath, volume->volumeId); // vol-XXX-libvirt.xml if (call_hooks(NC_EVENT_PRE_ATTACH, lpath)) { LOGERROR("[%s][%s] cancelled volume attachment via hooks\n", instance->instanceId, volume->volumeId); goto unroll; } // read in libvirt XML, which may have been modified by the hook above if ((xml = file2str(lpath)) == NULL) { LOGERROR("[%s][%s] failed to read volume XML from %s\n", instance->instanceId, volume->volumeId, lpath); goto unroll; } continue; unroll: ret = EUCA_ERROR; // TODO: unroll all volume attachments goto failed_dest; } sem_p(inst_sem); instance->migration_state = MIGRATION_READY; instance->bootTime = time(NULL); // otherwise nc_state.booting_cleanup_threshold will kick in change_state(instance, BOOTING); // not STAGING, since in that mode we don't poll hypervisor for info LOGINFO("[%s] migration destination ready %s > %s\n", instance->instanceId, instance->migration_src, instance->migration_dst); save_instance_struct(instance); error = add_instance(&global_instances, instance); copy_instances(); sem_v(inst_sem); if (error) { if (error == EUCA_DUPLICATE_ERROR) { LOGINFO("[%s] instance struct already exists (from previous migration?), deleting and re-adding...\n", instance->instanceId); error = remove_instance(&global_instances, instance); if (error) { LOGERROR("[%s] could not replace (remove) instance struct, failing...\n", instance->instanceId); goto failed_dest; } error = add_instance(&global_instances, instance); if (error) { LOGERROR("[%s] could not replace (add) instance struct, failing...\n", instance->instanceId); goto failed_dest; } } else { LOGERROR("[%s] could not add instance struct, failing...\n", instance->instanceId); goto failed_dest; } } continue; failed_dest: sem_p(inst_sem); // Just making sure... if (instance != NULL) { LOGERROR("[%s] setting instance to Teardown(cleaning) after destination failure to prepare for migration\n", instance->instanceId); // Set state to Teardown(cleaning) so source won't wait until timeout to roll back. instance->migration_state = MIGRATION_CLEANING; instance->terminationTime = time(NULL); change_state(instance, TEARDOWN); save_instance_struct(instance); add_instance(&global_instances, instance); // OK if this fails--that should mean it's already been added. copy_instances(); } // If no remaining incoming or pending migrations, deauthorize all clients. // TO-DO: Consolidate with similar sequence in handlers.c into a utility function? if (!incoming_migrations_in_progress) { int incoming_migrations_pending = 0; LOGINFO("[%s] no remaining active incoming migrations -- checking to see if there are any pending migrations\n", instance->instanceId); bunchOfInstances *head = NULL; for (head = global_instances; head; head = head->next) { if ((head->instance->migration_state == MIGRATION_PREPARING) || (head->instance->migration_state == MIGRATION_READY)) { LOGINFO("[%s] is pending migration, state='%s', deferring deauthorization of migration keys\n", head->instance->instanceId, migration_state_names[head->instance->migration_state]); incoming_migrations_pending++; } } // TO-DO: Add belt and suspenders? if (!incoming_migrations_pending) { LOGINFO("[%s] no remaining incoming or pending migrations -- deauthorizing all migration client keys\n", instance->instanceId); authorize_migration_keys("-D -r", NULL, NULL, NULL, FALSE); } } sem_v(inst_sem); // Set to generic EUCA_ERROR unless already set to a more-specific error. if (ret == EUCA_OK) { ret = EUCA_ERROR; } } else { LOGERROR("unexpected migration request (node %s is neither source nor destination)\n", pMeta->nodeName); ret = EUCA_ERROR; } } return ret; }
/* returns size of the file in bytes if OK, otherwise a negative error */ static long long get_cached_file (const char * user_id, const char * url, const char * file_id, const char * instance_id, const char * file_name, char * file_path, sem * s, int convert_to_disk, long long limit_mb) { char tmp_digest_path [BUFSIZE]; char cached_dir [BUFSIZE]; char cached_path [BUFSIZE]; char staging_path [BUFSIZE]; char digest_path [BUFSIZE]; snprintf (file_path, BUFSIZE, "%s/%s/%s/%s", sc_instance_path, user_id, instance_id, file_name); snprintf (tmp_digest_path, BUFSIZE, "%s-digest", file_path); snprintf (cached_dir, BUFSIZE, "%s/%s/cache/%s", sc_instance_path, EUCALYPTUS_ADMIN, file_id); /* cache is in admin's directory */ snprintf (cached_path, BUFSIZE, "%s/%s", cached_dir, file_name); snprintf (staging_path, BUFSIZE, "%s-staging", cached_path); snprintf (digest_path, BUFSIZE, "%s-digest", cached_path); retry: /* under a lock, figure out the state of the file */ sem_p (sc_sem); /***** acquire lock *****/ ensure_subdirectory_exists (file_path); /* creates missing directories */ struct stat mystat; int cached_exists = ! stat (cached_path, &mystat); int staging_exists = ! stat (staging_path, &mystat); int e = ERROR; int action; enum { ABORT, VERIFY, WAIT, STAGE }; if ( staging_exists ) { action = WAIT; } else { if ( cached_exists ) { action = VERIFY; } else { action = STAGE; } } /* we return the sum of these */ long long file_size_b = 0; long long digest_size_b = 0; /* while still under lock, decide whether to cache */ int should_cache = 0; if (action==STAGE) { e = walrus_object_by_url (url, tmp_digest_path, 0); /* get the digest to see how big the file is */ if (e==OK && stat (tmp_digest_path, &mystat)) { digest_size_b = (long long)mystat.st_size; } if (e==OK) { /* pull the size out of the digest */ char * xml_file = file2str (tmp_digest_path); if (xml_file) { file_size_b = str2longlong (xml_file, "<size>", "</size>"); free (xml_file); } if (file_size_b > 0) { long long full_size_b = file_size_b+digest_size_b; if (convert_to_disk) { full_size_b += swap_size_mb*MEGABYTE + MEGABYTE; /* TODO: take into account extra padding required for disks (over partitions) */ } if ( full_size_b/MEGABYTE + 1 > limit_mb ) { logprintfl (EUCAFATAL, "error: insufficient disk capacity remaining (%lldMB) in VM Type of instance %s for component %s\n", limit_mb, instance_id, file_name); action = ABORT; } else if ( ok_to_cache (cached_path, full_size_b) ) { /* will invalidate the cache, if needed */ ensure_path_exists (cached_dir); /* creates missing directories */ should_cache = 1; if ( touch (staging_path) ) { /* indicate that we'll be caching it */ logprintfl (EUCAERROR, "error: failed to create staging file %s\n", staging_path); action = ABORT; } } } else { logprintfl (EUCAERROR, "error: failed to obtain file size from digest %s\n", url); action = ABORT; } } else { logprintfl (EUCAERROR, "error: failed to obtain digest from %s\n", url); action = ABORT; } } sem_v (sc_sem); /***** release lock *****/ switch (action) { case STAGE: logprintfl (EUCAINFO, "downloding image into %s...\n", file_path); e = walrus_image_by_manifest_url (url, file_path, 1); /* for KVM, convert partition into disk */ if (e==OK && convert_to_disk) { sem_p (s); /* for the cached disk swap==0 and ephemeral==0 as we'll append them below */ if ((e=vrun("%s %s %d %d", disk_convert_command_path, file_path, 0, 0))!=0) { logprintfl (EUCAERROR, "error: partition-to-disk image conversion command failed\n"); } sem_v (s); /* recalculate file size now that it was converted */ if ( stat (file_path, &mystat ) != 0 ) { logprintfl (EUCAERROR, "error: file %s not found\n", file_path); } else if (mystat.st_size < 1) { logprintfl (EUCAERROR, "error: file %s has the size of 0\n", file_path); } else { file_size_b = (long long)mystat.st_size; } } /* cache the partition or disk, if possible */ if ( e==OK && should_cache ) { if ( (e=vrun ("cp -a %s %s", file_path, cached_path)) != 0) { logprintfl (EUCAERROR, "failed to copy file %s into cache at %s\n", file_path, cached_path); } if ( e==OK && (e=vrun ("cp -a %s %s", tmp_digest_path, digest_path)) != 0) { logprintfl (EUCAERROR, "failed to copy digest file %s into cache at %s\n", tmp_digest_path, digest_path); } } sem_p (sc_sem); if (should_cache) { unlink (staging_path); } if ( e ) { logprintfl (EUCAERROR, "error: failed to download file from Walrus into %s\n", file_path); unlink (file_path); unlink (tmp_digest_path); if (should_cache) { unlink (cached_path); unlink (digest_path); if ( rmdir(cached_dir) ) { logprintfl (EUCAWARN, "warning: failed to remove cache directory %s\n", cached_dir); } } } sem_v (sc_sem); break; case WAIT: logprintfl (EUCAINFO, "waiting for disapperance of %s...\n", staging_path); /* wait for staging_path to disappear, which means both either the * download succeeded or it failed */ if ( (e=wait_for_file (NULL, staging_path, 180, "cached image")) ) return 0L; /* yes, it is OK to fall through */ case VERIFY: logprintfl (EUCAINFO, "verifying cached file in %s...\n", cached_path); sem_p (sc_sem); /***** acquire lock *****/ e = ERROR; if ( stat (cached_path, &mystat ) != 0 ) { logprintfl (EUCAERROR, "error: file %s not found\n", cached_path); } else if (mystat.st_size < 1) { logprintfl (EUCAERROR, "error: file %s has the size of 0\n", cached_path); } else if ((e=walrus_verify_digest (url, digest_path))<0) { /* negative status => digest changed */ unlink (cached_path); unlink (staging_path); /* TODO: needed? */ unlink (digest_path); if ( rmdir (cached_dir) ) { logprintfl (EUCAWARN, "warning: failed to remove cache directory %s\n", cached_dir); } else { logprintfl (EUCAINFO, "due to failure, removed cache directory %s\n", cached_dir); } } else { file_size_b = mystat.st_size; /* touch the digest so cache can use mtime for invalidation */ if ( touch (digest_path) ) { logprintfl (EUCAERROR, "error: failed to touch digest file %s\n", digest_path); } else if ( stat (digest_path, &mystat) ) { logprintfl (EUCAERROR, "error: digest file %s not found\n", digest_path); } else { digest_size_b = (long long)mystat.st_size; } } sem_v (sc_sem); /***** release lock *****/ if (e<0) { /* digest changed */ if (action==VERIFY) { /* i.e. we did not download/waited for this file */ /* try downloading anew */ goto retry; } else { logprintfl (EUCAERROR, "error: digest mismatch, giving up\n"); return 0L; } } else if (e>0) { /* problem with file or digest */ return 0L; } else { /* all good - copy it, finally */ ensure_subdirectory_exists (file_path); /* creates missing directories */ if ( (e=vrun ("cp -a %s %s", cached_path, file_path)) != 0) { logprintfl (EUCAERROR, "failed to copy file %s from cache at %s\n", file_path, cached_path); return 0L; } } break; case ABORT: logprintfl (EUCAERROR, "get_cached_file() failed (errno=%d)\n", e); e = ERROR; } if (e==OK && file_size_b > 0 && convert_to_disk ) { // if all went well above long long ephemeral_mb = limit_mb - swap_size_mb - (file_size_b+digest_size_b)/MEGABYTE; if ( swap_size_mb>0L || ephemeral_mb>0L ) { sem_p (s); if ((e=vrun("%s %s %lld %lld", disk_convert_command_path, file_path, swap_size_mb, ephemeral_mb))!=0) { logprintfl (EUCAERROR, "error: failed to add swap or ephemeral to the disk image\n"); } sem_v (s); /* recalculate file size (again!) now that it was converted */ if ( stat (file_path, &mystat ) != 0 ) { logprintfl (EUCAERROR, "error: file %s not found\n", file_path); } else if (mystat.st_size < 1) { logprintfl (EUCAERROR, "error: file %s has the size of 0\n", file_path); } else { file_size_b = (long long)mystat.st_size; } } } if (e==OK && action!=ABORT) return file_size_b + digest_size_b; return 0L; }
/* thread that does the actual reboot */ static void * rebooting_thread (void *arg) { virConnectPtr *conn; ncInstance * instance = (ncInstance *)arg; struct stat statbuf; int rc = 0; // RESTARTING, // FAILED_RESTART, // SUCCESS_RESTART logprintfl (EUCADEBUG, "{%u} spawning rebooting thread\n", (unsigned int)pthread_self()); char * xml = file2str (instance->libvirtFilePath); if (xml == NULL) { logprintfl (EUCAERROR, "cannot obtain XML file %s\n", instance->libvirtFilePath); return NULL; } conn = check_hypervisor_conn(); if (! conn) { logprintfl (EUCAERROR, "cannot restart instance %s, abandoning it\n", instance->instanceId); change_state (instance, SHUTOFF); free (xml); return NULL; } sem_p(inst_sem); change_task_state (instance, REBOOTING); copy_instances (); sem_v(inst_sem); sem_p (hyp_sem); virDomainPtr dom = virDomainLookupByName(*conn, instance->instanceId); sem_v (hyp_sem); if (dom == NULL) { free (xml); sem_p(inst_sem); change_task_state (instance, FAILED_REBOOT); sem_v(inst_sem); return NULL; } sem_p (hyp_sem); // for KVM, must stop and restart the instance int error = virDomainDestroy (dom); // TODO: change to Shutdown? TODO: is this synchronous? virDomainFree(dom); sem_v (hyp_sem); if (error) { free (xml); sem_p(inst_sem); change_task_state (instance, FAILED_REBOOT); sem_v(inst_sem); return NULL; } #if 0 // domain is now shut down, create a new one with the same XML sem_p (hyp_sem); dom = virDomainCreateLinux (*conn, xml, 0); sem_v (hyp_sem); free (xml); char *remoteDevStr=NULL; // re-attach each volume previously attached for (int i=0; i < EUCA_MAX_VOLUMES; ++i) { ncVolume * volume = &instance->volumes[i]; if (strcmp (volume->stateName, VOL_STATE_ATTACHED) && strcmp (volume->stateName, VOL_STATE_ATTACHING)) continue; // skip the entry unless attached or attaching char attach_xml[1024]; int rc; // get credentials, decrypt them remoteDevStr = get_iscsi_target (volume->remoteDev); if (!remoteDevStr || !strstr(remoteDevStr, "/dev")) { logprintfl(EUCAERROR, "Reattach-volume: failed to get local name of host iscsi device\n"); rc = 1; } else { rc = gen_libvirt_attach_xml (volume->volumeId, instance, volume->localDevReal, remoteDevStr, attach_xml, sizeof(attach_xml)); } if (remoteDevStr) free (remoteDevStr); if (!rc) { int err; sem_p (hyp_sem); err = virDomainAttachDevice (dom, attach_xml); sem_v (hyp_sem); if (err) { logprintfl (EUCAERROR, "virDomainAttachDevice() failed (err=%d) XML=%s\n", err, attach_xml); } else { logprintfl (EUCAINFO, "reattached '%s' to '%s' in domain %s\n", volume->remoteDev, volume->localDevReal, instance->instanceId); } } } #endif int ret=restore_and_volume_instance(instance->instanceId); //20130122-th if (ret==1) { logprintfl (EUCAERROR, "Failed to REBOOT instance %s\n", instance->instanceId); change_state (instance, SHUTOFF); sem_p(inst_sem); change_task_state (instance, FAILED_REBOOT); sem_v(inst_sem); return NULL; } sem_p(inst_sem); change_task_state (instance, SUCCESS_REBOOT); save_instance_struct (instance); copy_instances(); sem_v (inst_sem); return NULL; }
int main (int argc, char *argv[]) { setprogname (argv[0]); if (argc != 2) usage (); str s = file2str (argv[1]); if (!s) fatal << "cannot open file: " << argv[1]; u_int niter = 10; u_int osz = 0; u_int32_t tot = 0; mstr *outbuf = NULL; u_int slen = s.len (); u_int out_avail = u_int ((slen / 1000) * 1001) + 16; for (u_int i = 0; i < niter; i++) { if (outbuf) delete outbuf; outbuf = New mstr (out_avail); warn << "+ starting compression\n"; startt (); osz = go (s, outbuf, out_avail); u_int t = stopt (); warn << "- ending compression (time=" << t << ")\n"; tot += t; } outbuf->setlen (osz); // // write out the buffer once, just to make sure we were getting reasonable // data output (and not some bullshit) // u_int i = 0; do { int rc = write (1, outbuf->cstr () + i, min<u_int> (2048, osz - i)); if (rc < 0) panic ("write error!\n"); i += rc; } while (i < osz); u_int64_t bw = osz / 1024; bw *= 1000000; bw /= tot; bw *= niter; warn ("Input: %d bytes\n" "Output: %d bytes\n" "Iterations: %d\n" "Usecs Total: %d\n" "Compression ratio * 1000: %d\n" "Throughput (kB/sec): %d\n", slen, osz, niter, tot, osz * 1000 / slen, u_int32_t (bw)); }
static void sclone (ref<asrv> s, ref<axprt_clone> x, sockaddr_in sin, svccb *sbp) { s->setcb (NULL); if (!sbp) { warn ("invalid connect from %s\n", inet_ntoa (sin.sin_addr)); return; } if (sbp->proc () != SFSPROC_CONNECT) { sbp->reject (PROC_UNAVAIL); return; } sfs_connectarg *arg = sbp->Xtmpl getarg<sfs_connectarg> (); u_int32_t rel; sfs_service service; str name; sfs_hash hostid; rpc_vec<sfs_extension, RPC_INFINITY> *extensions; switch (arg->civers) { case 4: rel = 4; service = arg->ci4->service; name = arg->ci4->name; hostid = arg->ci4->hostid; extensions = &arg->ci4->extensions; break; case 5: rel = arg->ci5->release; service = arg->ci5->service; if (!sfs_parsepath (arg->ci5->sname, &name, &hostid)) name = arg->ci5->sname; extensions = &arg->ci5->extensions; break; default: sbp->reject (GARBAGE_ARGS); return; } bhash<str> eh; for (const sfs_extension *ep = extensions->base (); ep < extensions->lim (); ep++) eh.insert (*ep); sfs_pathrevoke cert; str rawcert = file2str (revocationdir << "/" << armor32 (hostid.base (), hostid.size ())); if (rawcert && str2xdr (cert, rawcert)) { sfs_connectres res(SFS_REDIRECT); res.revoke->msg = cert.msg; res.revoke->sig = cert.sig; sbp->reply (&res); return; } const char *source = inet_ntoa (sin.sin_addr); server *srv; for (srv = serverlist.first; srv; srv = serverlist.next (srv)) if (srv->host == name && srv->hostid && *srv->hostid == hostid) if (srv->clone (x, sbp, source, rel, service, eh)) return; else break; for (srv = serverlist.first; srv; srv = serverlist.next (srv)) if (srv->host == name && !srv->hostid) if (srv->clone (x, sbp, source, rel, service, eh)) return; else break; for (srv = serverlist.first; srv; srv = serverlist.next (srv)) if (srv->host == name) if (srv->clone (x, sbp, source, rel, service, eh)) return; for (srv = serverlist.first; srv; srv = serverlist.next (srv)) if (srv->clone (x, sbp, source, rel, service, eh)) return; sbp->replyref (sfs_connectres (SFS_NOSUCHHOST)); }
int start_pppd(int unit) { int ret; FILE *fp; char options[80]; char *pppd_argv[] = { "/usr/sbin/pppd", "file", options, NULL}; char *l2tpd_argv[] = { "/usr/sbin/l2tpd", "-f", NULL}; char tmp[100], tmp1[32], prefix[] = "wanXXXXXXXXXX_"; mode_t mask; int pid; _dprintf("%s: unit=%d.\n", __FUNCTION__, unit); snprintf(prefix, sizeof(prefix), "wan%d_", unit); sprintf(options, "/tmp/ppp/options.wan%d", unit); mask = umask(0000); /* Generate options file */ if (!(fp = fopen(options, "w"))) { perror(options); umask(mask); return -1; } umask(mask); /* do not authenticate peer and do not use eap */ fprintf(fp, "noauth\n"); fprintf(fp, "refuse-eap\n"); fprintf(fp, "user '%s'\n", nvram_safe_get(strcat_r(prefix, "pppoe_username", tmp))); fprintf(fp, "password '%s'\n", nvram_safe_get(strcat_r(prefix, "pppoe_passwd", tmp))); if (nvram_match(strcat_r(prefix, "proto", tmp), "pptp")) { fprintf(fp, "plugin pptp.so\n"); fprintf(fp, "pptp_server '%s'\n", nvram_invmatch(strcat_r(prefix, "heartbeat_x", tmp), "") ? nvram_safe_get(strcat_r(prefix, "heartbeat_x", tmp)) : nvram_safe_get(strcat_r(prefix, "gateway_x", tmp))); /* see KB Q189595 -- historyless & mtu */ fprintf(fp, "nomppe-stateful mtu 1400\n"); if (nvram_match(strcat_r(prefix, "pptp_options_x", tmp), "-mppc")) { fprintf(fp, "nomppe nomppc\n"); } else if (nvram_match(strcat_r(prefix, "pptp_options_x", tmp), "+mppe-40")) { fprintf(fp, "require-mppe-40\n"); } else if (nvram_match(strcat_r(prefix, "pptp_options_x", tmp), "+mppe-56")) { fprintf(fp, "nomppe-40\n" "require-mppe-56\n"); } else if (nvram_match(strcat_r(prefix, "pptp_options_x", tmp), "+mppe-128")) { fprintf(fp, "nomppe-40\n" "nomppe-56\n" "require-mppe-128\n"); } } else { fprintf(fp, "nomppe nomppc\n"); } if (nvram_match(strcat_r(prefix, "proto", tmp), "pppoe")) { #ifdef RTCONFIG_DSL FILE* fp_dsl_mac; char buf_mac[32]; int trp_cnt; int rm_cnt; #endif fprintf(fp, "plugin rp-pppoe.so"); if (nvram_invmatch(strcat_r(prefix, "pppoe_service", tmp), "")) { fprintf(fp, " rp_pppoe_service '%s'", nvram_safe_get(strcat_r(prefix, "pppoe_service", tmp))); } if (nvram_invmatch(strcat_r(prefix, "pppoe_ac", tmp), "")) { fprintf(fp, " rp_pppoe_ac '%s'", nvram_safe_get(strcat_r(prefix, "pppoe_ac", tmp))); } fprintf(fp, " nic-%s\n", nvram_safe_get(strcat_r(prefix, "ifname", tmp))); fprintf(fp, "mru %s mtu %s\n", nvram_safe_get(strcat_r(prefix, "pppoe_mru", tmp)), nvram_safe_get(strcat_r(prefix, "pppoe_mtu", tmp))); // wait 10 seconds for DSL MAC address file ready #ifdef RTCONFIG_DSL if (nvram_match("dsl0_proto", "pppoa")) { strcpy(buf_mac, "00:11:22:33:44:55"); for (trp_cnt = 0; trp_cnt < 10; trp_cnt++) { fp_dsl_mac = fopen("/tmp/adsl/tc_mac.txt","r"); if (fp_dsl_mac != NULL) { fgets(buf_mac,sizeof(buf_mac),fp_dsl_mac); fclose(fp_dsl_mac); break; } usleep(1000*1000); } // remove cr lf in buf_mac for (rm_cnt = 0; rm_cnt < sizeof(buf_mac); rm_cnt++) { if (buf_mac[rm_cnt] == 0) break; if (buf_mac[rm_cnt] == 0x0a || buf_mac[rm_cnt] == 0x0d) { buf_mac[rm_cnt]=0; break; } } fprintf(fp, "rp_pppoe_sess %d:%s\n", 154, buf_mac); } #endif } if (nvram_invmatch(strcat_r(prefix, "proto", tmp), "l2tp")){ ret = nvram_get_int(strcat_r(prefix, "pppoe_idletime", tmp)); if (ret && nvram_match(strcat_r(prefix, "pppoe_demand", tmp), "1")) { fprintf(fp, "idle %d ", ret); if (nvram_invmatch(strcat_r(prefix, "pppoe_txonly_x", tmp), "0")) fprintf(fp, "tx_only "); fprintf(fp, "demand\n"); } fprintf(fp, "persist\n"); } fprintf(fp, "holdoff %s\n", nvram_invmatch(strcat_r(prefix, "pppoe_holdoff", tmp), "")?nvram_safe_get(tmp):"10"); // pppd re-call-time(s) fprintf(fp, "maxfail 0\n"); if (nvram_invmatch(strcat_r(prefix, "dnsenable_x", tmp), "0")) fprintf(fp, "usepeerdns\n"); fprintf(fp, "ipcp-accept-remote ipcp-accept-local noipdefault\n"); fprintf(fp, "ktune\n"); /* pppoe set these options automatically */ /* looks like pptp also likes them */ fprintf(fp, "default-asyncmap nopcomp noaccomp\n"); /* pppoe disables "vj bsdcomp deflate" automagically */ /* ccp should still be enabled - mppe/mppc requires this */ fprintf(fp, "novj nobsdcomp nodeflate\n"); /* echo failures */ fprintf(fp, "lcp-echo-interval 6\n"); fprintf(fp, "lcp-echo-failure 10\n"); fprintf(fp, "unit %d\n", unit); fprintf(fp, "linkname wan%d\n", unit); #ifdef RTCONFIG_IPV6 switch (get_ipv6_service()) { case IPV6_NATIVE: case IPV6_NATIVE_DHCP: case IPV6_MANUAL: fprintf(fp, "+ipv6\n"); break; } #endif /* user specific options */ fprintf(fp, "%s\n", nvram_safe_get(strcat_r(prefix, "pppoe_options_x", tmp))); fclose(fp); if (nvram_match(strcat_r(prefix, "proto", tmp), "l2tp")) { if (!(fp = fopen("/tmp/l2tp.conf", "w"))) { perror(options); return -1; } fprintf(fp, "# automagically generated\n" "global\n\n" "load-handler \"sync-pppd.so\"\n" "load-handler \"cmd.so\"\n\n" "section sync-pppd\n\n" "lac-pppd-opts \"file %s\"\n\n" "section peer\n" "port 1701\n" "peername %s\n" "hostname %s\n" "lac-handler sync-pppd\n" "persist yes\n" "maxfail %s\n" "holdoff %s\n" "hide-avps no\n" "section cmd\n\n", options, nvram_invmatch(strcat_r(prefix, "heartbeat_x", tmp), "") ? nvram_safe_get(strcat_r(prefix, "heartbeat_x", tmp)) : nvram_safe_get(strcat_r(prefix, "gateway_x", tmp)), nvram_invmatch(strcat_r(prefix, "hostname", tmp), "") ? // ham 0509 nvram_safe_get(strcat_r(prefix, "hostname", tmp)) : "localhost", nvram_invmatch(strcat_r(prefix, "pppoe_maxfail", tmp), "") ? nvram_safe_get(strcat_r(prefix, "pppoe_maxfail", tmp)) : "32767", nvram_invmatch(strcat_r(prefix, "pppoe_holdoff", tmp), "") ? nvram_safe_get(strcat_r(prefix, "pppoe_holdoff", tmp)) : "10"); fclose(fp); /* launch l2tp */ ret = _eval(l2tpd_argv, NULL, 0, &pid); int retry = 3; while(!pids("l2tpd") && retry--){ _dprintf("%s: wait l2tpd up at %d seconds...\n", __FUNCTION__, retry); sleep(1); } sleep(1); // when the pid of l2tpd is existed, also need to wait a more second. /* start-session */ ret = eval("/usr/sbin/l2tp-control", "start-session 0.0.0.0"); /* pppd sync nodetach noaccomp nobsdcomp nodeflate */ /* nopcomp novj novjccomp file /tmp/ppp/options.l2tp */ } else{ char pid_file[256], *value; int orig_pid; int wait_time = 0; memset(pid_file, 0, 256); snprintf(pid_file, 256, "/var/run/ppp-wan%d.pid", unit); if((value = file2str(pid_file)) != NULL && (orig_pid = atoi(value)) > 1){ _dprintf("%s: kill pppd(%d).\n", __FUNCTION__, orig_pid); kill(orig_pid, SIGHUP); sleep(1); while(check_process_exist(orig_pid) && wait_time < MAX_WAIT_FILE){ _dprintf("%s: kill pppd(%d).\n", __FUNCTION__, orig_pid); ++wait_time; kill(orig_pid, SIGTERM); sleep(1); } if(check_process_exist(orig_pid)){ kill(orig_pid, SIGKILL); sleep(1); } } if(value != NULL) free(value); ret = _eval(pppd_argv, NULL, 0, NULL); } return 0; }
int main (int argc, char **argv) { uint num_keys = 150; if (argc > 1) { num_keys = atoi (argv[1]); } srandom (time (NULL)); merkle_tree *tree = New merkle_tree_disk ("/tmp/index.mrk", "/tmp/internal.mrk", "/tmp/leaf.mrk", true); // if a trace is provided, execute the trace if (argc > 2) { str filename = argv[2]; str file = file2str (filename); rxx newline ("\\n"); vec<str> lines; split (&lines, newline, file); for (uint i = 0; i < lines.size(); i++) { if (i > num_keys) { warn << "did enough keys!\n"; exit(0); } static const rxx space_rx ("\\s+"); vec<str> parts; split (&parts, space_rx, lines[i]); if (parts.size() != 2) { continue; } chordID c; str2chordID (parts[1], c); if (parts[0] == "I") { warn << i << ") going to insert " << c << "\n"; tree->insert (c); } else { warn << i << ") going to remove " << c << "\n"; tree->remove (c); } tree->check_invariants (); } exit(0); } //tree->dump (); // inserts chordID c; for (uint i = 0; i < num_keys; i++) { c = make_randomID (); warn << "inserting " << c << " (" << i << ")\n"; tree->insert (c); tree->check_invariants(); } // lookups merkle_node_disk *n = (merkle_node_disk *) tree->lookup (to_merkle_hash (c)); warn << "found node " << n->count << ": \n"; if (n->isleaf ()) { merkle_key *k = n->keylist.first (); while (k != NULL) { warn << "\t" << k->id << "\n"; k = n->keylist.next (k); } } tree->lookup_release (n); assert (tree->key_exists (c)); // remove tree->remove (c); assert (!tree->key_exists (c)); //tree->dump (); chordID min = c; chordID max = ((chordID) 1) << 156; vec<chordID> keys = tree->get_keyrange (min, max, 65); for (uint i = 0; i < keys.size (); i++) { warn << "Found key " << keys[i] << " in range [" << min << "," << max << "]\n"; } delete tree; tree = NULL; unlink("/tmp/index.mrk"); unlink("/tmp/internal.mrk"); unlink("/tmp/leaf.mrk"); }
//! //! Restart or simply start the local DHCP server so it can pick up the new //! configuration. //! //! @return 0 on success or 1 if a failure occured //! //! @see //! //! @pre //! The DHCP server daemon must be present on the system and the 'config->dhcpDaemon' //! path must be properly set. //! //! @post //! on success, the DHCP server has been restarted. If the configuration file does not //! contain any data, the DHCP server is stopped. //! //! @note //! int eucanetd_kick_dhcpd_server(eucanetdConfig *config) { int ret = 0; int rc = 0; int pid = 0; int status = 0; char *psPid = NULL; char *psConfig = NULL; char sPidFileName[EUCA_MAX_PATH] = ""; char sConfigFileName[EUCA_MAX_PATH] = ""; char sLeaseFileName[EUCA_MAX_PATH] = ""; char sTraceFileName[EUCA_MAX_PATH] = ""; struct stat mystat = { 0 }; // Do we have a valid path? if (stat(config->dhcpDaemon, &mystat) != 0) { LOGERROR("Unable to find DHCP daemon binaries: '%s'\n", config->dhcpDaemon); return (1); } // Setup the path to the various files involved snprintf(sPidFileName, EUCA_MAX_PATH, NC_NET_PATH_DEFAULT "/euca-dhcp.pid", config->eucahome); snprintf(sLeaseFileName, EUCA_MAX_PATH, NC_NET_PATH_DEFAULT "/euca-dhcp.leases", config->eucahome); snprintf(sTraceFileName, EUCA_MAX_PATH, NC_NET_PATH_DEFAULT "/euca-dhcp.trace", config->eucahome); snprintf(sConfigFileName, EUCA_MAX_PATH, NC_NET_PATH_DEFAULT "/euca-dhcp.conf", config->eucahome); // Retrieve the PID of the current DHCP server process if running if (stat(sPidFileName, &mystat) == 0) { psPid = file2str(sPidFileName); pid = atoi(psPid); EUCA_FREE(psPid); // If the PID value is valid, kill the server if (pid > 1) { LOGDEBUG("attempting to kill old dhcp daemon (pid=%d)\n", pid); if ((rc = safekillfile(sPidFileName, config->dhcpDaemon, 9, config->cmdprefix)) != 0) { LOGWARN("failed to kill previous dhcp daemon\n"); } } } // Check to make sure the lease file is present if (stat(sLeaseFileName, &mystat) != 0) { // nope, just create an empty one LOGDEBUG("creating stub lease file (%s)\n", sLeaseFileName); if ((rc = touch(sLeaseFileName)) != 0) { LOGWARN("cannot create empty leasefile\n"); } } // We should be able to load the configuration file if ((psConfig = file2str(sConfigFileName)) != NULL) { // Do we have any "node-" statement if (strstr(psConfig, "node-")) { // Run the DHCP command rc = euca_execlp(&status, config->cmdprefix, config->dhcpDaemon, "-cf", sConfigFileName, "-lf", sLeaseFileName, "-pf", sPidFileName, "-tf", sTraceFileName, NULL); if (rc != EUCA_OK) { LOGERROR("Fail to restart DHCP server. exitcode='%d'\n", status); LOGDEBUG("DHCPD Server Command='%s %s %s %s %s %s %s %s %s %s'\n", config->cmdprefix, config->dhcpDaemon, "-cf", sConfigFileName, "-lf", sLeaseFileName, "-pf", sPidFileName, "-tf", sTraceFileName) ret = 1; } else { LOGDEBUG("DHCP server restarted successfully\n"); } } EUCA_FREE(psConfig); } return (ret); }
int node_config(int argc, char *argv[], NodeConfig *c, NodeSysConfig *s) { int ret; if (c == NULL) return NODE_CONFIG_RET_ERR_UNKNOWN; /* internal error */ /* initialize NodeConfig with undefined values */ bzero(c, sizeof(NodeConfig)); c->auto_connect = UNKNOWN; c->verbose = UNDEFINED_CFG_INT; c->daemon = UNDEFINED_CFG_INT; c->debug = UNDEFINED_CFG_INT; c->driver = HYPERVISOR_IS_KVM; /* parse command line options */ ret = __parse_opt(argc, argv, c); if (ret) return ret; /* to exit program */ /* check conf_path before reading it */ if (c->conf_path == NULL) { c->conf_path = strdup(DEFAULT_LYNODE_CONF_PATH); if (c->conf_path == NULL) return NODE_CONFIG_RET_ERR_NOMEM; } /* parse config file */ if (access(c->conf_path, R_OK) == 0) { ret = __parse_config(c); if (ret && ret != NODE_CONFIG_RET_ERR_NOCONF) return ret; /* to exit programe */ } /* set default values for auto_connect */ if (c->auto_connect == UNKNOWN) c->auto_connect = ALWAYS; /* read sysconf settings */ bzero(s, sizeof(NodeSysConfig)); s->node_tag = -1; if (c->sysconf_path == NULL) { c->sysconf_path = strdup(DEFAULT_LYNODE_SYSCONF_PATH); if (c->conf_path == NULL) return NODE_CONFIG_RET_ERR_NOMEM; } if (access(c->sysconf_path, W_OK) != 0) { if (lyutil_create_file(c->sysconf_path, 0) < 0) { logsimple(_("not able to write to %s\n"), c->sysconf_path); return NODE_CONFIG_RET_ERR_CMD; } } else { ret = __parse_sysconf(c->sysconf_path, s); if (ret) return ret; /* to exit program */ } /* read xml template */ if (c->vm_template_path) { c->vm_xml = file2str(c->vm_template_path, LIBVIRT_XML_MAX); if (c->vm_xml == NULL) { logsimple(_("error while reading %s\n"), c->vm_template_path); return NODE_CONFIG_RET_ERR_CMD; } } if (c->vm_template_net_nat_path) { c->vm_xml_net_nat = file2str(c->vm_template_net_nat_path, LIBVIRT_XML_MAX); if (c->vm_xml_net_nat == NULL) { logsimple(_("error while reading %s\n"), c->vm_template_net_nat_path); return NODE_CONFIG_RET_ERR_CMD; } } if (c->vm_template_net_br_path) { c->vm_xml_net_br = file2str(c->vm_template_net_br_path, LIBVIRT_XML_MAX); if (c->vm_xml_net_br == NULL) { logsimple(_("error while reading %s\n"), c->vm_template_net_br_path); return NODE_CONFIG_RET_ERR_CMD; } } if (c->vm_template_disk_path) { c->vm_xml_disk = file2str(c->vm_template_disk_path, LIBVIRT_XML_MAX); if (c->vm_xml_disk == NULL) { logsimple(_("error while reading %s\n"), c->vm_template_disk_path); return NODE_CONFIG_RET_ERR_CMD; } } /* set default values for unconfigured settings */ if (c->verbose == UNDEFINED_CFG_INT) c->verbose = 0; if (c->daemon == UNDEFINED_CFG_INT) c->daemon = 1; if (c->debug == UNDEFINED_CFG_INT) c->debug = 0; if (c->clc_port == 0) c->clc_port = DEFAULT_LYCLC_PORT; if (c->clc_mcast_ip == NULL) c->clc_mcast_ip = strdup(DEFAULT_LYCLC_MCAST_IP); if (c->clc_mcast_port == 0) c->clc_mcast_port = DEFAULT_LYCLC_MCAST_PORT; if (c->log_path == NULL) { c->log_path = strdup(DEFAULT_LYNODE_LOG_PATH); if (c->log_path == NULL) return NODE_CONFIG_RET_ERR_NOMEM; } if (c->pid_path == NULL) { c->pid_path = strdup(DEFAULT_LYNODE_PID_PATH); if (c->pid_path == NULL) return NODE_CONFIG_RET_ERR_NOMEM; } if (c->osm_conf_path == NULL) { c->osm_conf_path = strdup(DEFAULT_LYOSM_CONF_PATH); if (c->osm_conf_path == NULL) return NODE_CONFIG_RET_ERR_NOMEM; } if (c->osm_key_path == NULL) { c->osm_key_path = strdup(DEFAULT_LYOSM_KEY_PATH); if (c->osm_key_path == NULL) return NODE_CONFIG_RET_ERR_NOMEM; } if (c->node_data_dir == NULL) { c->node_data_dir = strdup(DEFAULT_LYNODE_DATA_DIR); if (c->node_data_dir == NULL) return NODE_CONFIG_RET_ERR_NOMEM; } if (c->net_primary == NULL) { c->net_primary = strdup(LUOYUN_INSTANCE_NET_DEFAULT); if (c->net_primary == NULL) return NODE_CONFIG_RET_ERR_NOMEM; } /* create necessary sub-directories for normal operation */ int len = strlen(c->node_data_dir); c->app_data_dir = malloc(len + 15); c->ins_data_dir = malloc(len + 15); c->trash_data_dir = malloc(len + 15); if (c->app_data_dir == NULL || c->ins_data_dir == NULL) return NODE_CONFIG_RET_ERR_NOMEM; sprintf(c->app_data_dir, "%s/appliances", c->node_data_dir); if (lyutil_create_dir(c->app_data_dir) != 0) { logsimple(_("failed creating directory of %s\n"), c->app_data_dir); return NODE_CONFIG_RET_ERR_CMD; } if (__clean_lockfile(c->app_data_dir) != 0) { logsimple(_("failed cleaning directory of %s\n"), c->app_data_dir); return NODE_CONFIG_RET_ERR_CMD; } sprintf(c->ins_data_dir, "%s/instances", c->node_data_dir); if (lyutil_create_dir(c->ins_data_dir) != 0) { logsimple(_("failed creating directory of %s\n"), c->ins_data_dir); return NODE_CONFIG_RET_ERR_CMD; } if (__clean_lockfile(c->ins_data_dir) != 0) { logsimple(_("failed cleaning directory of %s\n"), c->ins_data_dir); return NODE_CONFIG_RET_ERR_CMD; } sprintf(c->trash_data_dir, "%s/trash", c->node_data_dir); if (lyutil_create_dir(c->trash_data_dir) != 0) { logsimple(_("failed creating directory of %s\n"), c->trash_data_dir); return NODE_CONFIG_RET_ERR_CMD; } /* simple configuration validity checking */ if (__is_IP_valid(c->clc_mcast_ip, 1) == 0) { logsimple(_("cloud controller mcast ip is invalid\n")); return NODE_CONFIG_RET_ERR_CONF; } if (__is_port_valid(c->clc_mcast_port) == 0 ) { logsimple(_("cloud controller port is invalid\n")); return NODE_CONFIG_RET_ERR_CONF; } if (__is_port_valid(c->clc_port) == 0 ) { logsimple(_("cloud controller port is invalid\n")); return NODE_CONFIG_RET_ERR_CONF; } if ((c->auto_connect == DISABLE || c->clc_ip) && __is_IP_valid(c->clc_ip, 0) == 0) { logsimple(_("cloud controller ip is invalid<%s>\n"), c->clc_ip); return NODE_CONFIG_RET_ERR_CONF; } if (c->log_path) { if (access(c->log_path, F_OK) && lyutil_create_file(c->log_path, 0) < 0) { logsimple(_("not able to create %s\n"), c->log_path); return NODE_CONFIG_RET_ERR_CMD; } if (access(c->log_path, W_OK)) { logsimple(_("not able to write to %s\n"), c->log_path); return NODE_CONFIG_RET_ERR_CMD; } } return ret; }
//! //! Run a daemonized program and maintain its state. If a PID file is given, it will check if the //! process is currently running and if the running process matches the given program. If not, the //! current process will be terminated and restarted with the new program. If the process is running //! and matche our program name, it will be left alone. If the process is not currently running, //! it will be started. //! //! @param[in] psPidFilePath a constant string pointer to the PID file path //! @param[in] psRootWrap a constant string pointer to the rootwrap program location //! @param[in] force set to TRUE if we want to kill the process regardless of its state and restart it. Otherwise set to FALSE. //! @param[in] psProgram a constant string pointer to the pathname of a program which is to be executed //! @param[in] ... the list of string arguments to pass to the program //! //! @return 0 on success or 1 on failure //! //! @pre //! - psProgram should not be NULL //! - There more be more than 1 variable argument provided //! //! @post //! On success, the program is executed and its PID is recorded in the psPidFilePath location if provided. If //! the process is already running, nothing will change. On failure, depending of where it occured, the system //! is left into a non-deterministic state from the caller's perspective. //! //! @note //! //! @todo //! We should move this to something more global under util/euca_system.[ch] //! int eucanetd_run_program(const char *psPidFilePath, const char *psRootWrap, boolean force, const char *psProgram, ...) { #define PID_STRING_LEN 32 int i = 0; int rc = 0; char *psPidId = NULL; char *pString = NULL; char **argv = NULL; char sPid[PID_STRING_LEN] = ""; char sFilePath[EUCA_MAX_PATH] = ""; char sCommand[EUCA_MAX_PATH] = ""; const char *psProgramName = psProgram; FILE *pFh = NULL; pid_t pid = 0; boolean found = FALSE; va_list va = { {0} }; // Make sure we know what app we are running if (!psProgram) { return (1); } // turn variable arguments into a array of strings for the euca_execvp_fd() va_start(va, psProgram); { argv = build_argv(psProgram, va); } va_end(va); // Make sure we have a valid arg list if (argv == NULL) return (1); // // Set the psProgramName properly. If its currently the rootwrap program, then move to the // next argument in the list // if (!strcmp(psProgram, psRootWrap)) { // We should have another argument or I don't see how we can run rootwrap without something else?!?!? if (argv[1] == NULL) { free_char_list(argv); return (1); } // We're good, use the next argument psProgramName = argv[1]; } // Do we need to check if we have the exact same program running? if (psPidFilePath) { found = FALSE; // Does the PID file exists? if ((rc = check_file(psPidFilePath)) == 0) { // // read and make sure the command matches. If it does not match, we will need to restart. // if ((psPidId = file2str(psPidFilePath)) != NULL) { snprintf(sFilePath, EUCA_MAX_PATH, "/proc/%s/cmdline", psPidId); // Check if the process is running if (check_file(sFilePath) == 0) { // read the old command and make sure we have the same command running if ((pFh = fopen(sFilePath, "r")) != NULL) { if (fgets(sCommand, EUCA_MAX_PATH, pFh)) { if (strstr(sCommand, psProgramName)) { // process is running, and is indeed psProgram found = TRUE; } } fclose(pFh); } } EUCA_FREE(psPidId); } if (found) { // pidfile passed in and process is already running if (force) { // kill process and remove pidfile LOGTRACE("Stopping '%s'\n", psProgramName); rc = safekillfile(psPidFilePath, psProgramName, 9, psRootWrap); } else { // nothing to do LOGTRACE("Program '%s' running properly. Nothing to do.\n", psProgramName); free_char_list(argv); return (0); } } else { // pidfile passed in but process is not running unlink(psPidFilePath); } } } // Build the command string for debugging purpose for (i = 0, pString = sCommand; argv[i] != NULL; i++) { pString += snprintf(pString, (EUCA_MAX_PATH - (pString - sCommand)), "%s ", argv[i]); } rc = euca_execvp_fd(&pid, NULL, NULL, NULL, argv); LOGTRACE("Executed '%s'. PID=%d, RC=%d\n", sCommand, pid, rc); free_char_list(argv); if (psPidFilePath) { snprintf(sPid, PID_STRING_LEN, "%d", pid); rc = write2file(psPidFilePath, sPid); } return (rc); #undef PID_STRING_LEN }