//! //! 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); }
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; }
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; }
//! //! 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); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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(); }
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; }
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(); }
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; }
//! //! 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); }
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; } }
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; }
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; }
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; }
//! //! 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; }
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; }
/* 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; }
//! //! 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; }
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; }
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; }
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 {
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); }
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; }
//! //! 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); }
// 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); }