Esempio n. 1
0
// 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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
File: degz.C Progetto: Keloran/okws
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);
}
Esempio n. 5
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));
}
Esempio n. 6
0
//!
//!
//!
//! @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));
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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;
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
File: wpa.c Progetto: rogerhu/dd-wrt
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);
}
Esempio n. 12
0
//!
//! 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
}
Esempio n. 13
0
//!
//! 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;
}
Esempio n. 14
0
/* 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;
}
Esempio n. 15
0
/* 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;
}
Esempio n. 16
0
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));
}
Esempio n. 18
0
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;
}
Esempio n. 19
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");
}
Esempio n. 20
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);
}
Esempio n. 21
0
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;
}
Esempio n. 22
0
//!
//! 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
}