/** * Restores ebtables state from files. * * @param ebth [in] pointer to the EB table handler structure * * @return 0 on success. 1 on failure. */ int ebt_system_restore(ebt_handler *ebth) { int ret = EUCA_OK; if (euca_execlp(NULL, ebth->cmdprefix, "ebtables", "--atomic-file", ebth->ebt_filter_file, "-t", "filter", "--atomic-commit", NULL) != EUCA_OK) { copy_file(ebth->ebt_filter_file, "/tmp/euca_ebt_filter_file_failed"); LOGERROR("ebtables-restore failed. copying failed input file to '/tmp/euca_ebt_filter_file_failed' for manual retry.\n"); ret = 1; } if (euca_execlp(NULL, ebth->cmdprefix, "ebtables", "--atomic-file", ebth->ebt_nat_file, "-t", "nat", "--atomic-commit", NULL) != EUCA_OK) { copy_file(ebth->ebt_nat_file, "/tmp/euca_ebt_nat_file_failed"); LOGERROR("ebtables-restore failed. copying failed input file to '/tmp/euca_ebt_nat_file_failed' for manual retry.\n"); ret = 1; } unlink_handler_file(ebth->ebt_filter_file); unlink_handler_file(ebth->ebt_nat_file); unlink_handler_file(ebth->ebt_asc_file); return (ret); }
/** * Saves the current ebtables state to files. * * @param ebth [in] pointer to the EB table handler structure * * @return 0 on success. 1 on failure. */ int ebt_system_save(ebt_handler *ebth) { int ret = 0; if (euca_execlp(NULL, ebth->cmdprefix, "ebtables", "--atomic-file", ebth->ebt_filter_file, "-t", "filter", "--atomic-save", NULL) != EUCA_OK) { LOGERROR("ebtables-save -t filter failed\n"); ret = 1; } if (euca_execlp(NULL, ebth->cmdprefix, "ebtables", "--atomic-file", ebth->ebt_nat_file, "-t", "nat", "--atomic-save", NULL) != EUCA_OK) { LOGERROR("ebtables-save -t nat failed\n"); ret = 1; } if (euca_execlp_redirect(NULL, NULL, ebth->ebt_asc_file, FALSE, NULL, FALSE, ebth->cmdprefix, "ebtables", "--atomic-file", ebth->ebt_filter_file, "-t", "filter", "-L", NULL) != EUCA_OK) { LOGERROR("ebtables-list -t filter failed\n"); ret = 1; } if (euca_execlp_redirect(NULL, NULL, ebth->ebt_asc_file, TRUE, NULL, FALSE, ebth->cmdprefix, "ebtables", "--atomic-file", ebth->ebt_nat_file, "-t", "nat", "-L", NULL) != EUCA_OK) { LOGERROR("ebtables-list -t filter failed\n"); ret = 1; } return (ret); }
static int generate_migration_keys(char *host, char *credentials, boolean restart, ncInstance * instance) { int rc = EUCA_OK; char euca_rootwrap[EUCA_MAX_PATH] = ""; char generate_keys[EUCA_MAX_PATH] = ""; char *euca_base = getenv(EUCALYPTUS_ENV_VAR_NAME); char *instanceId = instance ? instance->instanceId : "UNSET"; static char *most_recent_credentials = NULL; static char *most_recent_host = NULL; if (!host || !credentials) { LOGERROR("[%s] called with invalid arguments for host and/or credentials: host=%s, creds=%s\n", SP(instanceId), SP(host), (credentials == NULL) ? "UNSET" : "present"); return (EUCA_INVALID_ERROR); } sem_p(hyp_sem); if (most_recent_credentials && most_recent_host && !strcmp(most_recent_credentials, credentials) && !strcmp(most_recent_host, host)) { LOGDEBUG("[%s] request to generate key using same information (host='%s', creds=%s) as previous request, skipping\n", instanceId, host, (credentials == NULL) ? "UNSET" : "present"); sem_v(hyp_sem); return (EUCA_OK); } if (!most_recent_credentials) { most_recent_credentials = strdup(credentials); LOGDEBUG("[%s] first generation of migration credentials\n", instanceId); } if (!most_recent_host) { most_recent_host = strdup(host); LOGDEBUG("[%s] first generation of migration host information: %s\n", instanceId, most_recent_host); } // So, something has changed. if (strcmp(most_recent_credentials, credentials)) { EUCA_FREE(most_recent_credentials); most_recent_credentials = strdup(credentials); LOGDEBUG("[%s] regeneration of migration credentials\n", instanceId); } if (strcmp(most_recent_host, host)) { EUCA_FREE(most_recent_host); most_recent_host = strdup(host); LOGDEBUG("[%s] regeneration of migration host information: %s\n", instanceId, most_recent_host); } // TO-DO: Add polling around incoming_migrations_in_progress to prevent restarts during migrations? snprintf(generate_keys, EUCA_MAX_PATH, EUCALYPTUS_GENERATE_MIGRATION_KEYS, ((euca_base != NULL) ? euca_base : "")); snprintf(euca_rootwrap, EUCA_MAX_PATH, EUCALYPTUS_ROOTWRAP, ((euca_base != NULL) ? euca_base : "")); LOGDEBUG("[%s] executing migration key-generator: '%s %s %s %s %s'\n", instanceId, euca_rootwrap, generate_keys, host, credentials, ((restart == TRUE) ? "restart" : "")); rc = euca_execlp(NULL, euca_rootwrap, generate_keys, host, credentials, ((restart == TRUE) ? "restart" : ""), NULL); sem_v(hyp_sem); if (rc) { LOGERROR("[%s] cmd '%s %s %s %s %s' failed %d\n", instanceId, euca_rootwrap, generate_keys, host, credentials, ((restart == TRUE) ? "restart" : ""), rc); return (EUCA_SYSTEM_ERROR); } LOGDEBUG("[%s] migration key generation succeeded\n", instanceId); return (EUCA_OK); }
//! //! Safely terminate a program executed by eucanetd_run_program(). //! //! @param[in] pid the PID of the program to kill //! @param[in] psProgramName a constant string pointer to the program name matching the pid //! @param[in] psRootwrap a constant string pointer to the rootwrap program location //! //! @return 0 on success or 1 on failure //! //! @pre //! - psProgramName should not be NULL //! - The program should be running //! //! @post //! On success, the program is terminated. On failure, we can't tell what happened for sure. //! //! @note //! //! @todo //! We should move this to something more global under util/euca_system.[ch] //! int eucanetd_kill_program(pid_t pid, const char *psProgramName, const char *psRootwrap) { int status = 0; FILE *FH = NULL; char sPid[16] = ""; char sSignal[16] = ""; char cmdstr[EUCA_MAX_PATH] = ""; char file[EUCA_MAX_PATH] = ""; if ((pid < 2) || !psProgramName) { return (EUCA_INVALID_ERROR); } snprintf(file, EUCA_MAX_PATH, "/proc/%d/cmdline", pid); if (check_file(file)) { return (EUCA_PERMISSION_ERROR); } if ((FH = fopen(file, "r")) != NULL) { if (!fgets(cmdstr, EUCA_MAX_PATH, FH)) { fclose(FH); return (EUCA_ACCESS_ERROR); } fclose(FH); } else { return (EUCA_ACCESS_ERROR); } // found running process if (strstr(cmdstr, psProgramName)) { // passed in cmd matches running cmd if (psRootwrap) { snprintf(sPid, 16, "%d", pid); snprintf(sSignal, 16, "-%d", SIGTERM); euca_execlp(NULL, psRootwrap, "kill", sSignal, sPid, NULL); if (timewait(pid, &status, 1) == 0) { LOGERROR("child process {%u} failed to terminate. Attempting SIGKILL.\n", pid); snprintf(sSignal, 16, "-%d", SIGKILL); euca_execlp(NULL, psRootwrap, "kill", sSignal, sPid, NULL); if (timewait(pid, &status, 1) == 0) { LOGERROR("child process {%u} failed to KILL. Attempting SIGKILL again.\n", pid); euca_execlp(NULL, psRootwrap, "kill", sSignal, sPid, NULL); if (timewait(pid, &status, 1) == 0) { return (1); } } } } else { kill(pid, SIGTERM); if (timewait(pid, &status, 1) == 0) { LOGERROR("child process {%u} failed to terminate. Attempting SIGKILL.\n", pid); kill(pid, SIGKILL); if (timewait(pid, &status, 1) == 0) { LOGERROR("child process {%u} failed to KILL. Attempting SIGKILL again.\n", pid); kill(pid, SIGKILL); if (timewait(pid, &status, 1) == 0) { return (1); } } } } } return (0); }
//! //! 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); }
//! //! 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 Always return 0 //! int main(int argc, char *argv[]) { int dom_ids[MAXDOMS] = { 0 }; int num_doms = 0; char *eucahome = NULL; char *hypervisor = NULL; char rootWrap[EUCA_MAX_PATH] = ""; char cmd[EUCA_MAX_PATH] = ""; char hypervisorURL[32] = ""; virConnectPtr conn = NULL; // logfile (NULL, EUCAFATAL); // suppress all messages if (argc != 2) { fprintf(stderr, "error: test_nc expects one parameter (name of hypervisor)\n"); exit(1); } hypervisor = argv[1]; if (!strcmp(hypervisor, "kvm") || !strcmp(hypervisor, "qemu")) { snprintf(hypervisorURL, 32, "qemu:///system"); } else if (!strcmp(hypervisor, "xen")) { snprintf(hypervisorURL, 32, "xen:///"); } else if (!strcmp(hypervisor, "not_configured")) { fprintf(stderr, "error: HYPERVISOR variable is not set in eucalyptus.conf\n"); exit(1); } else { fprintf(stderr, "error: hypervisor type (%s) is not recognized\n", hypervisor); exit(1); } // check that commands that NC needs are there if (euca_execlp(NULL, "perl", "--version", NULL) != EUCA_OK) { fprintf(stderr, "error: could not run perl\n"); exit(1); } if ((eucahome = getenv(EUCALYPTUS_ENV_VAR_NAME)) == NULL) { eucahome = strdup(""); // root by default } else { eucahome = strdup(eucahome); // Sanitize this string if (euca_sanitize_path(eucahome) != EUCA_OK) { EUCA_FREE(eucahome); eucahome = strdup(""); } } add_euca_to_path(eucahome); fprintf(stderr, "looking for system utilities...\n"); if (diskutil_init(0)) { EUCA_FREE(eucahome); exit(1); } // ensure hypervisor information is available fprintf(stderr, "ok\n\nchecking the hypervisor...\n"); snprintf(rootWrap, sizeof(rootWrap), EUCALYPTUS_ROOTWRAP, eucahome); if (!strcmp(hypervisor, "kvm") || !strcmp(hypervisor, "qemu")) { snprintf(cmd, sizeof(cmd), EUCALYPTUS_HELPER_DIR "/get_sys_info", eucahome); } else { snprintf(cmd, sizeof(cmd), EUCALYPTUS_HELPER_DIR "/get_xen_info", eucahome); } if (euca_execlp(NULL, rootWrap, cmd, NULL) != EUCA_OK) { fprintf(stderr, "error: could not run '%s %s'\n", rootWrap, cmd); EUCA_FREE(eucahome); exit(1); } // check that libvirt can query the hypervisor // NULL means local hypervisor if ((conn = virConnectOpen(hypervisorURL)) == NULL) { print_libvirt_error(); fprintf(stderr, "error: failed to connect to hypervisor\n"); EUCA_FREE(eucahome); exit(1); } if ((num_doms = virConnectListDomains(conn, dom_ids, MAXDOMS)) < 0) { print_libvirt_error(); fprintf(stderr, "error: failed to query running domains\n"); EUCA_FREE(eucahome); exit(1); } fprintf(stdout, "NC test was successful\n"); EUCA_FREE(eucahome); return (0); }
/** * Dumps ebtables hander state to files and restore this ebtables state into system. * * @param ebth [in] pointer to the EB table handler structure * * @return 0 on success. 1 on failure. */ int ebt_handler_deploy(ebt_handler *ebth) { int i = 0; int j = 0; int k = 0; char cmd[EUCA_MAX_PATH] = ""; if (!ebth || !ebth->init) { return (1); } // Create tmp files as non-root char *strptr = strdup(ebth->cmdprefix); ebt_table *tablesbak = ebth->tables; int maxtablesbak = ebth->max_tables; ebt_handler_init(ebth, strptr); ebth->tables = tablesbak; ebth->max_tables = maxtablesbak; EUCA_FREE(strptr); ebt_handler_update_refcounts(ebth); if (euca_execlp(NULL, ebth->cmdprefix, "ebtables", "--atomic-file", ebth->ebt_filter_file, "-t", "filter", "--atomic-init", NULL) != EUCA_OK) { LOGERROR("ebtables-save failed\n"); return (1); } if (euca_execlp(NULL, ebth->cmdprefix, "ebtables", "--atomic-file", ebth->ebt_nat_file, "-t", "nat", "--atomic-init", NULL) != EUCA_OK) { LOGERROR("ebtables-save failed\n"); return (1); } for (i = 0; i < ebth->max_tables; i++) { for (j = 0; j < ebth->tables[i].max_chains; j++) { if (strcmp(ebth->tables[i].chains[j].name, "EMPTY") && ebth->tables[i].chains[j].ref_count) { if (strcmp(ebth->tables[i].chains[j].name, "INPUT") && strcmp(ebth->tables[i].chains[j].name, "OUTPUT") && strcmp(ebth->tables[i].chains[j].name, "FORWARD") && strcmp(ebth->tables[i].chains[j].name, "PREROUTING") && strcmp(ebth->tables[i].chains[j].name, "POSTROUTING")) { if (!strcmp(ebth->tables[i].name, "filter")) { snprintf(cmd, EUCA_MAX_PATH, "%s ebtables --atomic-file %s -t %s -N %s", ebth->cmdprefix, ebth->ebt_filter_file, ebth->tables[i].name, ebth->tables[i].chains[j].name); if (euca_exec(cmd) != EUCA_OK) { LOGERROR("command failed: command=%s\n", cmd); } } else if (!strcmp(ebth->tables[i].name, "nat")) { snprintf(cmd, EUCA_MAX_PATH, "%s ebtables --atomic-file %s -t %s -N %s", ebth->cmdprefix, ebth->ebt_nat_file, ebth->tables[i].name, ebth->tables[i].chains[j].name); if (euca_exec(cmd) != EUCA_OK) { LOGERROR("command failed: command=%s\n", cmd); } } } } } for (j = 0; j < ebth->tables[i].max_chains; j++) { if (strcmp(ebth->tables[i].chains[j].name, "EMPTY") && ebth->tables[i].chains[j].ref_count) { for (k = 0; k < ebth->tables[i].chains[j].max_rules; k++) { if (!strcmp(ebth->tables[i].name, "filter")) { snprintf(cmd, EUCA_MAX_PATH, "%s ebtables --atomic-file %s -t %s -A %s %s", ebth->cmdprefix, ebth->ebt_filter_file, ebth->tables[i].name, ebth->tables[i].chains[j].name, ebth->tables[i].chains[j].rules[k].ebtrule); if (euca_exec(cmd) != EUCA_OK) { LOGERROR("command failed: command=%s\n", cmd); } } else if (!strcmp(ebth->tables[i].name, "nat")) { snprintf(cmd, EUCA_MAX_PATH, "%s ebtables --atomic-file %s -t %s -A %s %s", ebth->cmdprefix, ebth->ebt_nat_file, ebth->tables[i].name, ebth->tables[i].chains[j].name, ebth->tables[i].chains[j].rules[k].ebtrule); if (euca_exec(cmd) != EUCA_OK) { LOGERROR("command failed: command=%s\n", cmd); } } } } } } return (ebt_system_restore(ebth)); }