示例#1
0
//!
//! Handles the reboot request of an instance.
//!
//! @param[in] nc a pointer to the NC state structure to initialize
//! @param[in] pMeta a pointer to the node controller (NC) metadata structure
//! @param[in] instanceId the instance identifier string (i-XXXXXXXX)
//!
//! @return EUCA_OK on success or proper error code. Known error code returned include:
//!         EUCA_ERROR, EUCA_NOT_FOUND_ERROR, and EUCA_FATAL_ERROR.
//!
static int doRebootInstance(struct nc_state_t *nc, ncMetadata * pMeta, char *instanceId)
{
    pthread_t tcb = { 0 };
    ncInstance *instance = NULL;
    rebooting_thread_params *params = NULL;

    sem_p(inst_sem);
    {
        instance = find_instance(&global_instances, instanceId);
    }
    sem_v(inst_sem);

    if (instance == NULL) {
        LOGERROR("[%s] cannot find instance\n", instanceId);
        return (EUCA_NOT_FOUND_ERROR);
    }

    params = EUCA_ZALLOC(1, sizeof(rebooting_thread_params));
    memcpy(&(params->instance), instance, sizeof(ncInstance));
    memcpy(&(params->nc), nc, sizeof(struct nc_state_t));
    // since shutdown/restart may take a while, we do them in a thread
    if (pthread_create(&tcb, NULL, rebooting_thread, params)) {
        LOGERROR("[%s] failed to spawn a reboot thread\n", instanceId);
        return (EUCA_FATAL_ERROR);
    }
    set_corrid_pthread(get_corrid() != NULL ? get_corrid()->correlation_id : NULL, tcb);
    if (pthread_detach(tcb)) {
        LOGERROR("[%s] failed to detach the rebooting thread\n", instanceId);
        return (EUCA_FATAL_ERROR);
    }

    return (EUCA_OK);
}
示例#2
0
static int stale_blob_examiner (const blockblob * bb)
{
    char work_path [MAX_PATH];
    
    set_path (work_path, sizeof (work_path), NULL, NULL);
    int work_path_len = strlen (work_path);
    assert (work_path_len > 0);

    char * s = strstr(bb->blocks_path, work_path);
    if (s==NULL || s!=bb->blocks_path)
        return 0; // blob not under work blobstore path

    // parse the path past the work directory base
    safe_strncpy (work_path, bb->blocks_path, sizeof (work_path));
    s = work_path + work_path_len + 1;
    char * user_id = strtok (s, "/");
    char * inst_id = strtok (NULL, "/"); 
    char * file    = strtok (NULL, "/");

    ncInstance * instance = find_instance (instances, inst_id);
    if (instance == NULL) { // not found among running instances => stale
        // while we're here, try to delete extra files that aren't managed by the blobstore
        // TODO: ensure we catch any other files - perhaps by performing this cleanup after all blobs are deleted
        char path [MAX_PATH];
#define del_file(filename) snprintf (path, sizeof (path), "%s/work/%s/%s/%s", instances_path, user_id, inst_id, filename); unlink (path);
        del_file("instance.xml");
        del_file("libvirt.xml");
        del_file("console.log");
        del_file("instance.checkpoint");
        return 1;
    }

    return 0;
}
示例#3
0
static int
doRebootInstance(	struct nc_state_t *nc,
			ncMetadata *meta,
			char *instanceId) 
{
    sem_p (inst_sem); 
    ncInstance *instance = find_instance (&global_instances, instanceId);
    sem_v (inst_sem);
    if ( instance == NULL ) {
        logprintfl (EUCAERROR, "cannot find instance %s\n", instanceId);
        return ERROR;
    }
    
    pthread_t tcb;
    // since shutdown/restart may take a while, we do them in a thread
    if ( pthread_create (&tcb, NULL, rebooting_thread, (void *)instance) ) {
        logprintfl (EUCAERROR, "failed to spawn a reboot thread\n");
        return ERROR_FATAL;
    }
    if (pthread_detach(tcb)) {
      logprintfl (EUCAERROR, "failed to detach the rebooting thread\n");
      return ERROR_FATAL;
    }
    
    return OK;
}
示例#4
0
//!
//! Handles the reboot request of an instance.
//!
//! @param[in] nc a pointer to the NC state structure to initialize
//! @param[in] pMeta a pointer to the node controller (NC) metadata structure
//! @param[in] instanceId the instance identifier string (i-XXXXXXXX)
//!
//! @return EUCA_OK on success or proper error code. Known error code returned include: EUCA_ERROR
//!         and EUCA_FATAL_ERROR.
//!
static int doRebootInstance(struct nc_state_t *nc, ncMetadata * pMeta, char *instanceId)
{
    pthread_t tcb = { 0 };
    ncInstance *instance = NULL;

    sem_p(inst_sem);
    {
        instance = find_instance(&global_instances, instanceId);
    }
    sem_v(inst_sem);

    if (instance == NULL) {
        logprintfl(EUCAERROR, "[%s] cannot find instance\n", instanceId);
        return (EUCA_ERROR);
    }
    // since shutdown/restart may take a while, we do them in a thread
    if (pthread_create(&tcb, NULL, rebooting_thread, (void *)instance)) {
        logprintfl(EUCAERROR, "[%s] failed to spawn a reboot thread\n", instanceId);
        return (EUCA_FATAL_ERROR);
    }

    if (pthread_detach(tcb)) {
        logprintfl(EUCAERROR, "[%s] failed to detach the rebooting thread\n", instanceId);
        return (EUCA_FATAL_ERROR);
    }

    return (EUCA_OK);
}
示例#5
0
uint32_t RangeFinder::last_reading_ms(enum Rotation orientation) const
{
    AP_RangeFinder_Backend *backend = find_instance(orientation);
    if (backend == nullptr) {
        return 0;
    }
    return backend->last_reading_ms();
}
示例#6
0
uint16_t RangeFinder::voltage_mv_orient(enum Rotation orientation) const
{
    AP_RangeFinder_Backend *backend = find_instance(orientation);
    if (backend == nullptr) {
        return 0;
    }
    return backend->voltage_mv();
}
示例#7
0
int16_t RangeFinder::ground_clearance_cm_orient(enum Rotation orientation) const
{
    AP_RangeFinder_Backend *backend = find_instance(orientation);
    if (backend == nullptr) {
        return 0;
    }
    return backend->ground_clearance_cm();
}
示例#8
0
bool RangeFinder::has_data_orient(enum Rotation orientation) const
{
    AP_RangeFinder_Backend *backend = find_instance(orientation);
    if (backend == nullptr) {
        return false;
    }
    return backend->has_data();
}
示例#9
0
uint8_t RangeFinder::range_valid_count_orient(enum Rotation orientation) const
{
    AP_RangeFinder_Backend *backend = find_instance(orientation);
    if (backend == nullptr) {
        return 0;
    }
    return backend->range_valid_count();
}
示例#10
0
const Vector3f &RangeFinder::get_pos_offset_orient(enum Rotation orientation) const
{
    AP_RangeFinder_Backend *backend = find_instance(orientation);
    if (backend == nullptr) {
        return pos_offset_zero;
    }
    return backend->get_pos_offset();
}
示例#11
0
MAV_DISTANCE_SENSOR RangeFinder::get_mav_distance_sensor_type_orient(enum Rotation orientation) const
{
    AP_RangeFinder_Backend *backend = find_instance(orientation);
    if (backend == nullptr) {
        return MAV_DISTANCE_SENSOR_UNKNOWN;
    }
    return backend->get_mav_distance_sensor_type();
}
示例#12
0
文件: lwlib.c 项目: cpitclaudel/emacs
Widget
lw_get_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
{
  widget_instance* instance;

  instance = find_instance (id, parent, pop_up_p);
  return instance ? instance->widget : NULL;
}
示例#13
0
RangeFinder::RangeFinder_Status RangeFinder::status_orient(enum Rotation orientation) const
{
    AP_RangeFinder_Backend *backend = find_instance(orientation);
    if (backend == nullptr) {
        return RangeFinder_NotConnected;
    }
    return backend->status();
}
示例#14
0
static int
doTerminateInstance(	struct nc_state_t *nc,
			ncMetadata *meta,
			char *instanceId,
			int *shutdownState,
			int *previousState)
{
	ncInstance *instance, *vninstance;
	virConnectPtr *conn;
	int err;

	sem_p (inst_sem); 
	instance = find_instance(&global_instances, instanceId);
	sem_v (inst_sem);
	if (instance == NULL) 
		return NOT_FOUND;

	/* try stopping the KVM domain */
	conn = check_hypervisor_conn();
	if (conn) {
	        sem_p(hyp_sem);
	        virDomainPtr dom = virDomainLookupByName(*conn, instanceId);
		sem_v(hyp_sem);
		if (dom) {
			/* also protect 'destroy' commands, just in case */
			sem_p (hyp_sem);
			err = virDomainDestroy (dom);
			sem_v (hyp_sem);
			if (err==0) {
				logprintfl (EUCAINFO, "destroyed domain for instance %s\n", instanceId);
			}
			sem_p(hyp_sem);
			virDomainFree(dom); /* necessary? */
			sem_v(hyp_sem);
		} else {
			if (instance->state != BOOTING)
				logprintfl (EUCAWARN, "warning: domain %s to be terminated not running on hypervisor\n", instanceId);
		}
	} 

	/* change the state and let the monitoring_thread clean up state */
    sem_p (inst_sem);
    if (instance->state==BOOTING) {
        change_state (instance, CANCELED);
    } else {
        change_state (instance, SHUTOFF);
    }
    sem_v (inst_sem);
	*previousState = instance->stateCode;
	*shutdownState = instance->stateCode;

	return OK;
}
示例#15
0
//!
//! Callback used when checking for the integrity of the work blobstore.
//!
//! @param[in] bb pointer to the blockblob to examine
//!
//! @return EUCA_OK on success or EUCA_ERROR on failure
//!
//! @see check_backing_store()
//! @see blobstore_fsck()
//!
//! @pre The bb field must not be NULL.
//!
static int stale_blob_examiner(const blockblob * bb)
{
    char *s = NULL;
    char *user_id = NULL;
    char *inst_id = NULL;
    char *file = NULL;
    char path[EUCA_MAX_PATH] = "";
    char work_path[EUCA_MAX_PATH] = "";
    int work_path_len = 0;
    ncInstance *instance = NULL;

    set_path(work_path, sizeof(work_path), NULL, NULL);
    work_path_len = strlen(work_path);
    assert(work_path_len > 0);

    s = strstr(bb->blocks_path, work_path);
    if ((s == NULL) || (s != bb->blocks_path)) {
        // blob not under work blobstore path
        return (EUCA_OK);
    }
    // parse the path past the work directory base
    euca_strncpy(work_path, bb->blocks_path, sizeof(work_path));
    s = work_path + work_path_len + 1;
    user_id = strtok(s, "/");
    inst_id = strtok(NULL, "/");
    file = strtok(NULL, "/");

    if (((instance = find_instance(instances, inst_id)) == NULL)    // not found among instances => stale
        || instance->state == TEARDOWN) {   // found among instances, but is already marked as terminated

        // if this instance is not among those we know about,
        // load it into memory and report it in Teardown state
        //! @TODO technically, disk state for this instance is not gone,
        //! but it soon will be, once this examiner function returns error
        if ((instance == NULL) && ((instance = load_instance_struct(inst_id)) != NULL)) {
            LOGINFO("marking non-running instance %s as terminated\n", inst_id);
            instance->terminationTime = time(NULL); // set time to now, so record won't get expired immediately
            change_state(instance, TEARDOWN);
            int err = add_instance(instances, instance);    // we are not using locks because we assume the caller does
            if (err) {
                free_instance(&instance);
            }
        }
        // while we're here, try to delete extra files that aren't managed by the blobstore
        snprintf(path, sizeof(path), "%s/work/%s/%s", instances_path, user_id, inst_id);
        blobstore_delete_nonblobs(bb->store, path);
        return (EUCA_ERROR);
    }

    return (EUCA_OK);
}
示例#16
0
static int 
doAttachSystemDisk (    struct nc_state_t *nc,
                           ncMetadata *meta,
                           char *instanceId,
                           char *isoPath)
{
    ncInstance *instance;
    virConnectPtr *conn;
    virDomainPtr dom = NULL;
    char xml[MAX_PATH]={'\0'};
    int err;
    snprintf (xml, sizeof(xml), "<disk type='block' device='cdrom'><source dev='%s'/><target dev='hdc' bus='ide'/><readonly/></disk>", isoPath);  
    //logprintfl(EUCAINFO, "doAttachSystemDisk(): founded %s [%s---%s---%d]\n", instanceId,__FILE__, __FUNCTION__, __LINE__);
    sem_p(inst_sem);
    instance = find_instance(&global_instances, instanceId);
    sem_v(inst_sem);
    if (instance == NULL || (instance->state != RUNNING&& instance->state !=  BLOCKED&& instance->state !=PAUSED)) {
        logprintfl(EUCAINFO, "doAttachSystemDisk(): found %s failed or instance->state!=RUNNING||BLOCKED||PAUSED [file:%s---line:%d]\n", instanceId, __FILE__, __LINE__);
        return NOT_FOUND;
    }
    conn = check_hypervisor_conn();
    if (conn) {
/*
        snprintf(cmd, sizeof(cmd), "virsh attach-disk %s %s hdc --type cdrom --mode readonly",instanceId, isoPath);
        logprintfl(EUCAINFO, "xiongm: cmd=%s [%s---%s---%d]\n",cmd, __FILE__, __FUNCTION__, __LINE__);
        system(cmd);
*/
        dom = NULL;
        sem_p(hyp_sem);
        dom = virDomainLookupByName(*conn, instanceId);
        sem_v(hyp_sem);
        if (dom) {
            sem_p (hyp_sem);
            err = virDomainAttachDevice (dom, xml);
            sem_v (hyp_sem);
            if(err != 0) {
                logprintfl(EUCAINFO,"virDomainAttachDevice failed. err=%d\n",err);
                return 1;
            }
        }
        logprintfl(EUCAINFO,"doAttachSystemDisk success.\n");
        return 0;  
    }
    else {
        logprintfl(EUCAINFO, "doAttachSystemDisk(): no connect hypervisior [file:%s---line:%d]\n",__FILE__, __LINE__);
        return 1;
    }       
}
示例#17
0
文件: lwlib.c 项目: cpitclaudel/emacs
Widget
lw_make_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
{
  widget_instance* instance;
  widget_info* info;

  instance = find_instance (id, parent, pop_up_p);
  if (!instance)
    {
      info = get_widget_info (id, False);
      if (!info)
	return NULL;
      instance = allocate_widget_instance (info, parent, pop_up_p);
      initialize_widget_instance (instance);
    }
  if (!instance->widget)
    abort ();
  return instance->widget;
}
示例#18
0
static int doRestoreAInstance(struct nc_state_t *nc, ncMetadata *meta, char *instanceId) {

    sem_p(inst_sem);
    ncInstance *instance = find_instance(&global_instances, instanceId);
    sem_v(inst_sem);
    
    if (instance == NULL || (instance->state != SHUTOFF && instance->state != TRASHED)) {
        logprintfl(EUCAINFO, "doRestoreAInstance: found instance %s in global_instances error or instance->state!=SHUTOFF||TRASHED \n", instanceId);
        return NOT_FOUND;
    }  
    
    if(instance->state == SHUTOFF) {
        pthread_t tcb;
        if(pthread_create(&tcb, NULL, restoring_thread, (void *)instance)) {
            logprintfl (EUCAERROR, "failed to spawn a restore thread\n");
            return ERROR_FATAL;
        }
        if (pthread_detach(tcb)) {
        logprintfl (EUCAERROR, "failed to detach the restoring thread\n");
        return ERROR_FATAL;
        }
    } else { //instance->state == TRASHED      
        sem_p (inst_sem);
        change_state(instance,SHUTOFF);       
        save_instance_struct(instance);
        sem_v (inst_sem);
        logprintfl(EUCAINFO, "doRestoreAInstance restore instance form TRASHED TO SHUTOFF success next to running it instanceId=%s \n", instanceId);
       //add 20130106-xm
        pthread_t tcb;
        if(pthread_create(&tcb, NULL, restoring_thread, (void *)instance)) {
            logprintfl (EUCAERROR, "failed to spawn a restore thread\n");
            return ERROR_FATAL;
        }
        if (pthread_detach(tcb)) {
        logprintfl (EUCAERROR, "failed to detach the restoring thread\n");
        return ERROR_FATAL;
        }
        // end 20130106-xm
    }
    
    return OK;
}
示例#19
0
static int doRebootInstance(	struct nc_state_t *nc,
				ncMetadata *meta,
				char *instanceId) 
{
    ncInstance *instance;
    virConnectPtr *conn;

    sem_p (inst_sem); 
    instance = find_instance(&global_instances, instanceId);
    sem_v (inst_sem);
    if ( instance == NULL ) return NOT_FOUND;
    
    /* reboot the Xen domain */
    conn = check_hypervisor_conn();
    if (conn) {
        sem_p(hyp_sem);
        virDomainPtr dom = virDomainLookupByName(*conn, instanceId);
	sem_v(hyp_sem);
        if (dom) {
            /* also protect 'reboot', just in case */
            sem_p (hyp_sem);
            int err=virDomainReboot (dom, 0);
            sem_v (hyp_sem);
            if (err==0) {
                logprintfl (EUCAINFO, "[%s] rebooting Xen domain for instance\n", instanceId);
            }
	    sem_p(hyp_sem);
            virDomainFree(dom); /* necessary? */
	    sem_v(hyp_sem);
        } else {
            if (instance->state != BOOTING && instance->state != STAGING) {
                logprintfl (EUCAWARN, "[%s] domain to be rebooted not running on hypervisor\n", instanceId);
            }
        }
    }

    return 0;
}
示例#20
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)
{
    char *xml = NULL;
    char resourceName[1][MAX_SENSOR_NAME_LEN] = { "" };
    char resourceAlias[1][MAX_SENSOR_NAME_LEN] = { "" };
    ncInstance *instance = NULL;
    struct nc_state_t *nc = NULL;
    virDomainPtr dom = NULL;
    virConnectPtr conn = NULL;
    rebooting_thread_params *params = ((rebooting_thread_params *) arg);
    nc = &(params->nc);

    sem_p(inst_sem);
    {
        instance = find_instance(&global_instances, params->instanceId);
    }
    sem_v(inst_sem);

    if (instance == NULL) {
        LOGERROR("[%s] cannot find instance\n", params->instanceId);
        EUCA_FREE(params)
        return NULL;
    }
示例#21
0
static int doShutdownInstance(struct nc_state_t *nc, ncMetadata * meta, char * instanceId, char *taskId) {

    ncInstance *instance;
    virConnectPtr *conn;
    int err;
    logprintfl(EUCAINFO, "doShutdownInstance(): founded %s taskId=%s [%s---%s---%d]\n", instanceId,taskId, __FILE__, __FUNCTION__, __LINE__);
    sem_p(inst_sem);
    instance = find_instance(&global_instances, instanceId);
    sem_v(inst_sem);
    
    if (instance == NULL || (instance->state != RUNNING&& instance->state !=  BLOCKED&& instance->state != PAUSED)){
        logprintfl(EUCAINFO, "doShutdownInstance(): %s not in global_instances or instance->state!=RUNNING|BLOCKED|PAUSED \n", instanceId);
        return NOT_FOUND;
    }
    
    struct thread_params_t * params=NULL;
    params = malloc (sizeof (struct thread_params_t));
    if (params==NULL) 
    {       
        return ERROR;
    }   
    bzero (params, sizeof (struct thread_params_t));
    params->instance=instance;
    params->taskId=strdup(taskId);
    
    pthread_t tcb;
    if(pthread_create(&tcb, NULL, shutdowning_thread, (void *)params)) {
        logprintfl (EUCAERROR, "failed to spawn a shutdowning thread\n");
        return ERROR_FATAL;
    }
    if (pthread_detach(tcb)) {
    logprintfl (EUCAERROR, "failed to detach the shutdowning thread\n");
    return ERROR_FATAL;
    }
    return OK;
}
示例#22
0
/* perform integrity check on instances directory, including the cache:
 * remove any files from non-running Eucalyptus instances, delete files
 * from cache that are not complete, return the amount of bytes used up by
 * everything
 */
long long scFSCK (bunchOfInstances ** instances)
{
    long long total_size = 0;
    struct stat mystat;

    if (instances==NULL) return -1;
    
    logprintfl (EUCAINFO, "checking the integrity of instances directory (%s)\n", sc_instance_path);

    /* let us not 'rm -rf /' accidentally */
    if (strlen(sc_instance_path)<2 || 
        sc_instance_path[0]!='/' ) {
        logprintfl (EUCAFATAL, "error: instances directory cannot be /, sorry\n");
        return -1; 
    }

    if (stat (sc_instance_path, &mystat) < 0) {
        logprintfl (EUCAFATAL, "error: could not stat %s\n", sc_instance_path);
        return -1;
    }
    total_size += mystat.st_size;

    DIR * insts_dir;
    if ((insts_dir=opendir(sc_instance_path))==NULL) {
        logprintfl (EUCAFATAL, "error: could not open instances directory %s\n", sc_instance_path);
        return -1;
    }

    /*** run through all users ***/

    char * cache_path = NULL;
    struct dirent * inst_dir_entry;
    while ((inst_dir_entry=readdir(insts_dir))!=NULL) {
        char * uname = inst_dir_entry->d_name;
        char user_path [BUFSIZE];
        struct dirent * user_dir_entry;
        DIR * user_dir;

        if (!strcmp(".", uname) || 
            !strcmp("..", uname))
            continue;

        snprintf (user_path, BUFSIZE, "%s/%s", sc_instance_path, uname);
        if ((user_dir=opendir(user_path))==NULL) {
            logprintfl (EUCAWARN, "warning: unopeneable directory %s\n", user_path);
            continue;
        }

        /*** run through all instances of a user ***/
        while ((user_dir_entry=readdir(user_dir))!=NULL) {
            char * iname = user_dir_entry->d_name;
            
            if (!strcmp(".", iname) ||
                !strcmp("..", iname))
                continue;
            
            char instance_path [BUFSIZE];
            snprintf (instance_path, BUFSIZE, "%s/%s", user_path, iname);

            if (!strcmp("cache", iname) &&
                	!strcmp(EUCALYPTUS_ADMIN, uname)) { /* cache is in admin's dir */
		if (cache_path) {
                    logprintfl (EUCADEBUG, "Found a second cache_path?\n");
		    free(cache_path);
		}
                cache_path = strdup (instance_path);
                continue;
            }

            /* spare directories of running instances, but count their usage */
            if (find_instance (instances, iname)) {
                long long bytes = dir_size (instance_path);
                if (bytes>0) {
                    logprintfl (EUCAINFO, "- running instance %s directory, size=%d\n", iname, bytes);
                    total_size += bytes;
                } else if (bytes==0) {
                    logprintfl (EUCAWARN, "warning: empty instance directory %s\n", instance_path);
                } else {
                    logprintfl (EUCAWARN, "warning: non-standard instance directory %s\n", instance_path);
                } 
                continue;
            }

            /* looks good - destroy it */
            if (vrun ("rm -rf %s", instance_path)) {
                logprintfl (EUCAWARN, "warning: failed to remove %s\n", instance_path);
            }
        }
        closedir (user_dir);
    }
    closedir (insts_dir);

    /*** scan the cache ***/
    long long cache_bytes = init_cache (cache_path);
    free (cache_path);
    if (cache_bytes < 0) {
        return -1;
    }
    
    return total_size + cache_bytes;
}
示例#23
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, char ** resourceLocations, int resourceLocationsLen)
{
    int ret = EUCA_OK;
    int credentials_prepared = 0;
    char *libvirt_xml_modified = NULL;

    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);
                update_resource_locations(&(instance->params), resourceLocations, resourceLocationsLen);
                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;
            instance->migrationTime = time(NULL); //In preparing state, so set migrationTime.
            euca_strncpy(instance->migration_src, sourceNodeName, HOSTNAME_SIZE);
            euca_strncpy(instance->migration_dst, destNodeName, HOSTNAME_SIZE);
            euca_strncpy(instance->migration_credentials, credentials, CREDENTIAL_SIZE);
            update_resource_locations(&(instance->params), resourceLocations, resourceLocationsLen);
            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;

            //Fix for EUCA-10433, need instance struct in global_instances prior to doing volume ops
            //The monitor thread will now pick up the instance, so the migrationTime must be set
            sem_p(inst_sem);
            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;
                }
            }
            
            if (vbr_parse(&(instance->params), pMeta) != EUCA_OK) {
                goto failed_dest;
            }
            // set up networking
            char brname[IF_NAME_LEN] = "";
            if (!strcmp(nc->pEucaNet->sMode, NETMODE_MANAGED)) {
                snprintf(brname, IF_NAME_LEN, "%s", instance->groupIds[0]);
            } else {
                snprintf(brname, IF_NAME_LEN, "%s", nc->pEucaNet->sBridgeDevice);
            }
            euca_strncpy(instance->params.guestNicDeviceName, brname, sizeof(instance->params.guestNicDeviceName));
            // 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);

                ebs_volume_data *vol_data = NULL;
                char *libvirt_xml = NULL;
                char serial[128];
                char bus[16];
                set_serial_and_bus(volume->volumeId, volume->devName, serial, sizeof(serial), bus, sizeof(bus));

                if ((ret = connect_ebs(volume->devName, serial, bus, nc, instance->instanceId, volume->volumeId, volume->attachmentToken, &libvirt_xml, &vol_data)) != EUCA_OK) {
                    goto unroll;
                }
                // update the volume struct with connection string obtained from SC
                euca_strncpy(volume->connectionString, vol_data->connect_string, sizeof(volume->connectionString));
                // save volume info into vol-XXX-libvirt.xml for future detach
                if (create_vol_xml(instance->instanceId, volume->volumeId, libvirt_xml, &libvirt_xml_modified) != EUCA_OK) {
                    goto unroll;
                }

                continue;
unroll:
                ret = EUCA_ERROR;

                // @TODO: unroll all previous ones
                //  for (int uv = v - 1; uv >= 0; uv--) {
                //    disconnect_ebs(nc, instance->instanceId, volume->volumeId, )
                //  }

                goto failed_dest;
            }

                        // build any secondary network interface xml files
            for (int w=0; w < EUCA_MAX_NICS; w++) {
                if (strlen(instance->secNetCfgs[w].interfaceId) == 0)
                    continue;
                gen_libvirt_nic_xml(instance->instancePath, instance->secNetCfgs[w].interfaceId);
            }

            sem_p(inst_sem);
            instance->migration_state = MIGRATION_READY;
            instance->migrationTime = 0; //Reset the timer, to ensure monitoring thread handles this properly. This is required when setting BOOTING state
            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);
            copy_instances();
            sem_v(inst_sem);
            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;
}
示例#24
0
static int
doRunInstance(		struct nc_state_t *nc,
			ncMetadata *meta,
			char *instanceId,
			char *reservationId,
			virtualMachine *params, 
			char *imageId, char *imageURL, 
			char *kernelId, char *kernelURL, 
			char *ramdiskId, char *ramdiskURL, 
			char *keyName, 
			//			char *privMac, char *privIp, int vlan, 
			netConfig *netparams,
			char *userData, char *launchIndex,
			char **groupNames, int groupNamesSize,
			ncInstance **outInst)
{
    ncInstance * instance = NULL;
    * outInst = NULL;
    pid_t pid;
    netConfig ncnet;
    int error;

    memcpy(&ncnet, netparams, sizeof(netConfig));

    /* check as much as possible before forking off and returning */
    sem_p (inst_sem);
    instance = find_instance (&global_instances, instanceId);
    sem_v (inst_sem);
    if (instance) {
        logprintfl (EUCAFATAL, "Error: instance %s already running\n", instanceId);
        return 1; /* TODO: return meaningful error codes? */
    }
    if (!(instance = allocate_instance (instanceId, 
                                        reservationId,
                                        params, 
                                        imageId, imageURL,
                                        kernelId, kernelURL,
                                        ramdiskId, ramdiskURL,
                                        instance_state_names[PENDING], 
                                        PENDING, 
                                        meta->userId, 
                                        &ncnet, keyName,
                                        userData, launchIndex, groupNames, groupNamesSize))) {
        logprintfl (EUCAFATAL, "Error: could not allocate instance struct\n");
        return 2;
    }
    change_state(instance, STAGING);

    sem_p (inst_sem); 
    error = add_instance (&global_instances, instance);
    sem_v (inst_sem);
    if ( error ) {
        free_instance (&instance);
        logprintfl (EUCAFATAL, "Error: could not save instance struct\n");
        return error;
    }

    instance->launchTime = time (NULL);
    /*
      instance->params.mem = params->mem;
      instance->params.cores = params->cores;
      instance->params.disk = params->disk;
      strcpy (instance->ncnet.privateIp, "0.0.0.0");
      strcpy (instance->ncnet.publicIp, "0.0.0.0");
    */

    /* do the potentially long tasks in a thread */
    pthread_attr_t* attr = (pthread_attr_t*) malloc(sizeof(pthread_attr_t));
    if (!attr) { 
        free_instance (&instance);
        logprintfl (EUCAFATAL, "Warning: out of memory\n");
        return 1;
    }
    pthread_attr_init(attr);
    pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED);
    
    if ( pthread_create (&(instance->tcb), attr, startup_thread, (void *)instance) ) {
        pthread_attr_destroy(attr);
        logprintfl (EUCAFATAL, "failed to spawn a VM startup thread\n");
        sem_p (inst_sem);
        remove_instance (&global_instances, instance);
        sem_v (inst_sem);
        free_instance (&instance);
	if (attr) free(attr);
        return 1;
    }
    pthread_attr_destroy(attr);
    if (attr) free(attr);

    * outInst = instance;
    return 0;

}
示例#25
0
static int
doAttachVolume (	struct nc_state_t *nc,
			ncMetadata *meta,
			char *instanceId,
			char *volumeId,
			char *remoteDev,
			char *localDev)
{
    int ret = OK, rc;
    ncInstance * instance;
    char localDevReal[32];
    virConnectPtr *conn;
    struct stat statbuf;

    // fix up format of incoming local dev name, if we need to
    ret = convert_dev_names (localDev, localDevReal, NULL);
    if (ret)
        return ret;

    sem_p (inst_sem); 
    instance = find_instance(&global_instances, instanceId);
    sem_v (inst_sem);
    if ( instance == NULL ) 
        return NOT_FOUND;

    /* try attaching to the Xen domain */
    conn = check_hypervisor_conn();
    if (conn) {
        sem_p(hyp_sem);
        virDomainPtr dom = virDomainLookupByName(*conn, instanceId);
	sem_v(hyp_sem);
        if (dom) {

            int err = 0;
            char xml [1024];
            int is_iscsi_target = 0;
            char *local_iscsi_dev;
            rc = 0;
            if(check_iscsi(remoteDev)) {
                is_iscsi_target = 1;
                /*get credentials, decrypt them*/
                //parse_target(remoteDev);
                /*login to target*/
                local_iscsi_dev = connect_iscsi_target(nc->connect_storage_cmd_path, remoteDev);
		if (!local_iscsi_dev || !strstr(local_iscsi_dev, "/dev")) {
		  logprintfl(EUCAERROR, "AttachVolume(): failed to connect to iscsi target\n");
		  rc = 1;
		} else {
		  snprintf (xml, 1024, "<disk type='block'><driver name='phy'/><source dev='%s'/><target dev='%s'/></disk>", local_iscsi_dev, localDevReal);
		}
            } else {
	        snprintf (xml, 1024, "<disk type='block'><driver name='phy'/><source dev='%s'/><target dev='%s'/></disk>", remoteDev, localDevReal);
                rc = stat(remoteDev, &statbuf);
                if (rc) {
                   logprintfl(EUCAERROR, "AttachVolume(): cannot locate local block device file '%s'\n", remoteDev);
                   rc = 1;
                }
	    }
            if (!rc) {
	        /* protect Xen calls, just in case */
                sem_p (hyp_sem);
                err = virDomainAttachDevice (dom, xml);
                sem_v (hyp_sem);
		if (err) {
                   logprintfl (EUCAERROR, "AttachVolume() failed (err=%d) XML=%s\n", err, xml);
//                   rc = doDetachVolume(nc, meta, instanceId, volumeId, remoteDev, localDev, 1);
                   ret = ERROR;
		} else {
                   logprintfl (EUCAINFO, "attached %s to %s in domain %s\n", remoteDev, localDevReal, instanceId);
		}
            } else { 
                ret = ERROR;
	    }

	    sem_p(hyp_sem);
            virDomainFree(dom);
	    sem_v(hyp_sem);
            if(is_iscsi_target) {
	      if (local_iscsi_dev) free(local_iscsi_dev);
            }
        } else {
            if (instance->state != BOOTING && instance->state != STAGING) {
                logprintfl (EUCAWARN, "warning: domain %s not running on hypervisor, cannot attach device\n", instanceId);
            }
            ret = ERROR;
        }
    } else {
        ret = ERROR;
    }

    if (ret==OK) {
        ncVolume * volume;

        sem_p (inst_sem);
        volume = add_volume (instance, volumeId, remoteDev, localDevReal, localDevReal, "attached");
	scSaveInstanceInfo(instance); /* to enable NC recovery */
        sem_v (inst_sem);
        if ( volume == NULL ) {
            logprintfl (EUCAFATAL, "ERROR: Failed to save the volume record, aborting volume attachment\n");
            return ERROR;
        }
    }

    return ret;
}
示例#26
0
static int
doDetachVolume (	struct nc_state_t *nc,
			ncMetadata *meta,
			char *instanceId,
			char *volumeId,
			char *remoteDev,
			char *localDev,
			int force)
{
    int ret = OK;
    ncInstance * instance;
    char localDevReal[32];
    virConnectPtr *conn;

    // fix up format of incoming local dev name, if we need to
    ret = convert_dev_names (localDev, localDevReal, NULL);
    if (ret)
        return ret;

    sem_p (inst_sem); 
    instance = find_instance(&global_instances, instanceId);
    sem_v (inst_sem);
    if ( instance == NULL ) 
        return NOT_FOUND;

    /* try attaching to the Xen domain */
    conn = check_hypervisor_conn(); 
    if (conn) {
        sem_p(hyp_sem);
        virDomainPtr dom = virDomainLookupByName(*conn, instanceId);
	sem_v(hyp_sem);
        if (dom) {
	    int err = 0, fd, rc, pid, status;
            char xml [1024], tmpfile[32], cmd[MAX_PATH];
	    FILE *FH;
	            int is_iscsi_target = 0;
            char *local_iscsi_dev;
            if(check_iscsi(remoteDev)) {
                is_iscsi_target = 1;
                /*get credentials, decrypt them*/
                //parse_target(remoteDev);
                /*logout from target*/
                if((local_iscsi_dev = get_iscsi_target(nc->get_storage_cmd_path, remoteDev)) == NULL)
                    return ERROR;
                snprintf (xml, 1024, "<disk type='block'><driver name='phy'/><source dev='%s'/><target dev='%s'/></disk>", local_iscsi_dev, localDevReal);
            } else {
                snprintf (xml, 1024, "<disk type='block'><driver name='phy'/><source dev='%s'/><target dev='%s'/></disk>", remoteDev, localDevReal);
	    }
            /* protect Xen calls, just in case */
            sem_p (hyp_sem);
	    pid = fork();
	    if (!pid) {
	      char cmd[MAX_PATH];
	      snprintf(tmpfile, 32, "/tmp/detachxml.XXXXXX");
	      fd = mkstemp(tmpfile);
	      if (fd > 0) {
		write(fd, xml, strlen(xml));
		close(fd);
		snprintf(cmd, MAX_PATH, "%s %s `which virsh` %s %s %s", nc->detach_cmd_path, nc->rootwrap_cmd_path, instanceId, localDevReal, tmpfile);
		rc = system(cmd);
		rc = rc>>8;
		unlink(tmpfile);
	      } else {
		logprintfl(EUCAERROR, "could not write to tmpfile for detach XML: %s\n", tmpfile);
		rc = 1;
	      } 
	      exit(rc);
	    } else {
示例#27
0
static int
doGetConsoleOutput(	struct nc_state_t *nc,
			ncMetadata *meta,
			char *instanceId,
			char **consoleOutput) {

  char *console_output=NULL, *console_append=NULL, *console_main=NULL, *tmp=NULL;
  char console_file[MAX_PATH], dest_file[MAX_PATH], cmd[MAX_PATH];
  char userId[48];
  int rc, fd, ret;
  struct stat statbuf;
  ncInstance *instance=NULL;

  int bufsize, pid, status;

  *consoleOutput = NULL;

  // find the instance record
  sem_p (inst_sem); 
  instance = find_instance(&global_instances, instanceId);
  if (instance) {
    snprintf(userId, 48, "%s", instance->userId);
  	snprintf(console_file, 1024, "%s/console.append.log", instance->instancePath);
  }
  sem_v (inst_sem);
  if (!instance) {
    logprintfl(EUCAERROR, "[%s] cannot locate instance\n", instanceId);
    return(1);
  }
  rc = stat(console_file, &statbuf);
  if (rc >= 0) {
    fd = open(console_file, O_RDONLY);
    if (fd >= 0) {
      console_append = malloc(4096);
      if (console_append) {
	bzero(console_append, 4096);
	rc = read(fd, console_append, (4096)-1);
      }
      close(fd);
    }
  }


  bufsize = sizeof(char) * 1024 * 64;
  console_main = malloc(bufsize);
  if (!console_main) {
    logprintfl(EUCAERROR, "[%s] out of memory!\n", instanceId);
    if (console_append) free(console_append);
    return(1);
  }
  bzero(console_main, bufsize);

  if (getuid() != 0) {
    snprintf(console_file, MAX_PATH, "/var/log/xen/console/guest-%s.log", instanceId);
    snprintf(dest_file, MAX_PATH, "%s/console.log", instance->instancePath);
    snprintf(cmd, MAX_PATH, "%s cp %s %s", nc->rootwrap_cmd_path, console_file, dest_file);
    rc = system(cmd);
    if (!rc) {
      // was able to copy xen guest console file, read it
      snprintf(cmd, MAX_PATH, "%s chown %s:%s %s", nc->rootwrap_cmd_path, nc->admin_user_id, nc->admin_user_id, dest_file);
      rc = system(cmd);
      if (!rc) {
	tmp = file2str_seek(dest_file, bufsize, 1);
	if (tmp) {
	  snprintf(console_main, bufsize, "%s", tmp);
	  free(tmp);
	} else {
	  snprintf(console_main, bufsize, "NOT SUPPORTED");
	}
      } else {
	snprintf(console_main, bufsize, "NOT SUPPORTED");
      }
    } else {
      snprintf(console_main, bufsize, "NOT SUPPORTED");
    }
  } else {

    snprintf(console_file, MAX_PATH, "/tmp/consoleOutput.%s", instanceId);
    
    pid = fork();
    if (pid == 0) {
      int fd;
      fd = open(console_file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
      if (fd < 0) {
	// error
      } else {
	dup2(fd, 2);
	dup2(2, 1);
	close(0);
	// TODO: test virsh console:
	// rc = execl(rootwrap_command_path, rootwrap_command_path, "virsh", "console", instanceId, NULL);
	rc = execl("/usr/sbin/xm", "/usr/sbin/xm", "console", instanceId, NULL);
	fprintf(stderr, "execl() failed\n");
	close(fd);
      }
      exit(0);
    } else {
      int count;
      fd_set rfds;
      struct timeval tv;
      struct stat statbuf;
      
      count=0;
      while(count < 10000 && stat(console_file, &statbuf) < 0) {count++;}
      fd = open(console_file, O_RDONLY);
      if (fd < 0) {
	logprintfl (EUCAERROR, "[%s] could not open consoleOutput file %s for reading\n", instanceId, console_file);
      } else {
	FD_ZERO(&rfds);
	FD_SET(fd, &rfds);
	tv.tv_sec = 0;
	tv.tv_usec = 500000;
	rc = select(1, &rfds, NULL, NULL, &tv);
	bzero(console_main, bufsize);
	
	count = 0;
	rc = 1;
	while(rc && count < 1000) {
	  rc = read(fd, console_main, bufsize-1);
	  count++;
	}
	close(fd);
      }
      kill(pid, 9);
      wait(&status);
    }
    
    unlink(console_file);
  }
  
  ret = 1;
  console_output = malloc( (64*1024) + 4096 );
  if (console_output) {
    bzero(console_output, (64*1024) + 4096 );
    if (console_append) {
      strncat(console_output, console_append, 4096);
    }
    if (console_main) {
      strncat(console_output, console_main, 1024*64);
    }
    *consoleOutput = base64_enc((unsigned char *)console_output, strlen(console_output));
    ret = 0;
  }
  
  if (console_append) free(console_append);
  if (console_main) free(console_main);
  if (console_output) free(console_output);
  
  return(ret);
}
示例#28
0
int main (int argc, char **argv) 
{
    printf ("=====> testing misc.c\n");

    test_command("date");
    test_command("ls / -l | sort");
    test_command("/foo");
    {
        char c = 0;
        long l = 0;
        int i = 0;
        long long ll = 0;

        sscanf_lines  ("a1\na\na2\n", "a%d", &i);
        assert (i==1);
        sscanf_lines  ("a\nab3\na   4\na5", "a %d", &i);
        assert (i==4);
        sscanf_lines  ("", "%d", &i);
        sscanf_lines  ("\n\n\n", "%d", &i);
        sscanf_lines  ("abcdefg6", "g%d", &i);
        assert (i!=6);
        sscanf_lines  ("abcdefg", "ab%cdefg", &c);
        assert (c=='c');
        sscanf_lines  ("a\na    7\na\n", "a %ld", &l);
        assert (l==7L);
        sscanf_lines  ("a\n8a\na9\n", "a %lld", &ll);
        assert (ll==9L);
    }

    printf ("=====> testing data.c\n");
    {
#define INSTS 50
        bunchOfInstances * bag = NULL;
        ncInstance * inst = NULL;
        ncInstance * Insts[INSTS];
        int i, n;
        
        printf ("========> testing instance struct management\n");
        free_instance (NULL);
        free_instance (&inst);
        inst = allocate_instance ("the-uuid", "i1", NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0);
        assert(inst!=NULL);
        free_instance (&inst);
        assert(inst==NULL);
        
        n = total_instances (&bag);
        assert(n==0);
        bag=NULL;
        
        inst = find_instance(&bag, "foo");
        assert(inst==NULL);
        bag=NULL;
        
        n = remove_instance(&bag, NULL);
        assert(n!=0);
        bag=NULL;
        
        for (i=0; i<INSTS; i++) {
            char id[10];
            sprintf(id, "i-%d", i);
            inst = Insts[i] = allocate_instance ("the-uuid", id, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0);
            assert (inst!=NULL);
            n = add_instance(&bag, inst);
            assert (n==0);
        }
        n = total_instances (&bag);
        assert (n==INSTS);
        n = remove_instance(&bag, Insts[0]);
        assert (n==0);
        n = remove_instance(&bag, Insts[INSTS-1]);
        assert (n==0);
        n = total_instances (&bag);
        assert (n==INSTS-2);

        printf ("========> testing volume struct management\n");
        ncVolume * v;
        inst = allocate_instance ("the-uuid", "i2", NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0);
        assert(inst!=NULL);
        for (i=0; i<EUCA_MAX_VOLUMES; i++) {
            char id[10];
            sprintf (id, "v-%d", i);
            v = save_volume (inst, id, "rd", "ld", "ldr", VOL_STATE_ATTACHED);
            assert (v!=NULL);
        }
        assert (is_volume_used (v));
        assert (save_volume (inst, "too-much", "rd", "ld", "ldr", VOL_STATE_ATTACHED)==NULL);
        assert (save_volume (inst, v->volumeId, NULL, NULL, NULL, NULL)!=NULL);
        assert (save_volume (inst, v->volumeId, "RD", NULL, NULL, NULL)!=NULL);
        assert (save_volume (inst, v->volumeId, NULL, "LD", NULL, NULL)!=NULL);
        assert (save_volume (inst, v->volumeId, NULL, NULL, "LDR", NULL)!=NULL);
        assert (save_volume (inst, v->volumeId, NULL, NULL, NULL, VOL_STATE_DETACHED)!=NULL);
        assert (strcmp (v->remoteDev, "RD") == 0);
        assert (save_volume (inst, "v-x1", NULL, NULL, NULL, VOL_STATE_ATTACHING)!=NULL);
        assert (save_volume (inst, "v-x2", NULL, NULL, NULL, VOL_STATE_ATTACHING)==NULL);
        assert (save_volume (inst, "v-x1", NULL, NULL, NULL, VOL_STATE_DETACHING)!=NULL);
        assert (save_volume (inst, "v-x2", NULL, NULL, NULL, VOL_STATE_ATTACHING)==NULL);
        assert (save_volume (inst, "v-x1", NULL, NULL, NULL, VOL_STATE_DETACHING_FAILED)!=NULL);
        assert (save_volume (inst, "v-x2", NULL, NULL, NULL, VOL_STATE_ATTACHING)==NULL);
        assert (free_volume (inst, "v-x1")!=NULL);
        for (i=0; i<EUCA_MAX_VOLUMES-1; i++) {
            char id[10];
            sprintf (id, "v-%d", i);
            v = free_volume (inst, id);
            assert (v!=NULL);
        }
        free_instance (&inst);
        assert(inst==NULL);        
    }

    printf ("OK\n");
    return 0;
}
示例#29
0
//!
//! Handles the console output retrieval request.
//!
//! @param[in]  nc a pointer to the NC state structure to initialize
//! @param[in]  pMeta a pointer to the node controller (NC) metadata structure
//! @param[in]  instanceId the instance identifier string (i-XXXXXXXX)
//! @param[out] consoleOutput a pointer to the unallocated string that will contain the output
//!
//! @return EUCA_OK on success or EUCA_ERROR and EUCA_NOT_FOUND_ERROR on failure.
//!
static int doGetConsoleOutput(struct nc_state_t *nc, ncMetadata * pMeta, char *instanceId, char **consoleOutput)
{
    int rc = 0;
    int fd = 0;
    int ret = EUCA_OK;
    int readsize = 0;
    char *console_output = NULL;
    char *console_append = NULL;
    char *console_main = NULL;
    char console_file[MAX_PATH] = "";
    char userId[48] = "";
    ncInstance *instance = NULL;
    struct stat statbuf = { 0 };

    *consoleOutput = NULL;
    readsize = 64 * 1024;

    // find the instance record
    sem_p(inst_sem);
    {
        if ((instance = find_instance(&global_instances, instanceId)) != NULL) {
            snprintf(console_file, 1024, "%s/console.append.log", instance->instancePath);
            snprintf(userId, 48, "%s", instance->userId);
        }
    }
    sem_v(inst_sem);

    if (!instance) {
        logprintfl(EUCAERROR, "[%s] cannot locate instance\n", instanceId);
        return (EUCA_NOT_FOUND_ERROR);
    }
    // read from console.append.log if it exists into dynamically allocated 4K console_append buffer
    if ((rc = stat(console_file, &statbuf)) >= 0) {
        if (diskutil_ch(console_file, nc->admin_user_id, nc->admin_user_id, 0) != EUCA_OK) {
            logprintfl(EUCAERROR, "[%s] failed to change ownership of %s\n", instanceId, console_file);
            return (EUCA_ERROR);
        }

        if ((fd = open(console_file, O_RDONLY)) >= 0) {
            if ((console_append = EUCA_ZALLOC(4096, sizeof(char))) != NULL) {
                rc = read(fd, console_append, (4096) - 1);
            }
            close(fd);
        }
    }

    sem_p(inst_sem);
    {
        snprintf(console_file, MAX_PATH, "%s/console.log", instance->instancePath);
    }
    sem_v(inst_sem);

    // read the last 64K from console.log or the whole file, if smaller, into dynamically allocated 64K console_main buffer
    if ((rc = stat(console_file, &statbuf)) >= 0) {
        if (diskutil_ch(console_file, nc->admin_user_id, nc->admin_user_id, 0) != EUCA_OK) {
            logprintfl(EUCAERROR, "[%s] failed to change ownership of %s\n", instanceId, console_file);
            EUCA_FREE(console_append);
            return (EUCA_ERROR);
        }

        if ((fd = open(console_file, O_RDONLY)) >= 0) {
            if ((rc = lseek(fd, (off_t) (-1 * readsize), SEEK_END)) < 0) {
                if ((rc = lseek(fd, (off_t) 0, SEEK_SET)) < 0) {
                    logprintfl(EUCAERROR, "[%s] cannot seek to beginning of file\n", instanceId);
                    if (console_append)
                        EUCA_FREE(console_append);
                    close(fd);
                    return (EUCA_ERROR);
                }
            }

            if ((console_main = EUCA_ZALLOC(readsize, sizeof(char))) != NULL) {
                rc = read(fd, console_main, (readsize) - 1);
            }
            close(fd);
        } else {
            logprintfl(EUCAERROR, "[%s] cannot open '%s' read-only\n", instanceId, console_file);
        }
    } else {
        logprintfl(EUCAERROR, "[%s] cannot stat console_output file '%s'\n", instanceId, console_file);
    }

    // concatenate console_append with console_main, base64-encode this, and put into dynamically allocated buffer consoleOutput
    ret = EUCA_ERROR;
    if ((console_output = EUCA_ZALLOC((readsize) + 4096, sizeof(char))) != NULL) {
        if (console_append) {
            strncat(console_output, console_append, 4096);
        }

        if (console_main) {
            strncat(console_output, console_main, readsize);
        }

        *consoleOutput = base64_enc((unsigned char *)console_output, strlen(console_output));
        ret = EUCA_OK;
    }

    EUCA_FREE(console_append);
    EUCA_FREE(console_main);
    EUCA_FREE(console_output);
    return (ret);
}
示例#30
0
// return true if we have a range finder with the specified orientation
bool RangeFinder::has_orientation(enum Rotation orientation) const
{
    return (find_instance(orientation) != nullptr);
}