int create_instance_backing (ncInstance * instance) { int ret = ERROR; virtualMachine * vm = &(instance->params); artifact * sentinel = NULL; // ensure instance directory exists set_path (instance->instancePath, sizeof (instance->instancePath), instance, NULL); if (ensure_directories_exist (instance->instancePath, 0, NULL, "root", BACKING_DIRECTORY_PERM) == -1) goto out; // set various instance-directory-relative paths in the instance struct set_path (instance->xmlFilePath, sizeof (instance->xmlFilePath), instance, "instance.xml"); set_path (instance->libvirtFilePath, sizeof (instance->libvirtFilePath), instance, "libvirt.xml"); set_path (instance->consoleFilePath, sizeof (instance->consoleFilePath), instance, "console.log"); if (strstr (instance->platform, "windows")) { // generate the floppy file for windows instances if (makeWindowsFloppy (nc_state.home, instance->instancePath, instance->keyName, instance->instanceId)) { logprintfl (EUCAERROR, "[%s] error: could not create windows bootup script floppy\n", instance->instanceId); goto out; } else { set_path (instance->floppyFilePath, sizeof (instance->floppyFilePath), instance, "floppy"); } } char work_prefix [1024]; // {userId}/{instanceId} set_id (instance, NULL, work_prefix, sizeof (work_prefix)); // compute tree of dependencies sentinel = vbr_alloc_tree (vm, // the struct containing the VBR FALSE, // for Xen and KVM we do not need to make disk bootable TRUE, // make working copy of runtime-modifiable files (instance->do_inject_key)?(instance->keyName):(NULL), // the SSH key instance->instanceId); // ID is for logging if (sentinel == NULL) { logprintfl (EUCAERROR, "[%s] error: failed to prepare backing for instance\n", instance->instanceId); goto out; } sem_p (disk_sem); // download/create/combine the dependencies int rc = art_implement_tree (sentinel, work_bs, cache_bs, work_prefix, INSTANCE_PREP_TIMEOUT_USEC); sem_v (disk_sem); if (rc != OK) { logprintfl (EUCAERROR, "[%s] error: failed to implement backing for instance\n", instance->instanceId); goto out; } if (save_instance_struct (instance)) // update instance checkpoint now that the struct got updated goto out; ret = OK; out: if (sentinel) art_free (sentinel); return ret; }
//! //! Implement the backing store for a given instance //! //! @param[in] instance pointer to the instance //! @param[in] is_migration_dest //! //! @return EUCA_OK on success or EUCA_ERROR on failure //! //! @pre The instance parameter must not be NULL. //! //! @post //! int create_instance_backing(ncInstance * instance, boolean is_migration_dest) { int rc = 0; int ret = EUCA_ERROR; virtualMachine *vm = &(instance->params); artifact *sentinel = NULL; char work_prefix[1024] = { 0 }; // {userId}/{instanceId} // set various instance-directory-relative paths in the instance struct set_instance_paths(instance); // ensure instance directory exists if (ensure_directories_exist(instance->instancePath, 0, NULL, "root", BACKING_DIRECTORY_PERM) == -1) goto out; if (strstr(instance->platform, "windows")) { // generate the floppy file for windows instances if (makeWindowsFloppy(nc_state.home, instance->instancePath, instance->keyName, instance->instanceId)) { LOGERROR("[%s] could not create windows bootup script floppy\n", instance->instanceId); goto out; } else { set_path(instance->floppyFilePath, sizeof(instance->floppyFilePath), instance, "floppy"); } } else if (strlen(instance->instancePk) > 0) { // TODO: credential floppy is limited to Linux instances ATM LOGDEBUG("[%s] creating floppy for instance credential\n", instance->instanceId); if (make_credential_floppy(nc_state.home, instance)) { LOGERROR("[%s] could not create credential floppy\n", instance->instanceId); goto out; } else { set_path(instance->floppyFilePath, sizeof(instance->floppyFilePath), instance, "floppy"); } } set_id(instance, NULL, work_prefix, sizeof(work_prefix)); // if this looks like a partition m1.small image, make it a bootable disk virtualMachine *vm2 = NULL; LOGDEBUG("vm->virtualBootRecordLen=%d\n", vm->virtualBootRecordLen); if (vm->virtualBootRecordLen == 5) { // TODO: make this check more robust // as an experiment, construct a new VBR, without swap and ephemeral virtualMachine vm_copy; vm2 = &vm_copy; memcpy(vm2, vm, sizeof(virtualMachine)); bzero(vm2->virtualBootRecord, EUCA_MAX_VBRS * sizeof(virtualBootRecord)); vm2->virtualBootRecordLen = 0; virtualBootRecord *emi_vbr = NULL; for (int i = 0; i < EUCA_MAX_VBRS && i < vm->virtualBootRecordLen; i++) { virtualBootRecord *vbr = &(vm->virtualBootRecord[i]); if (vbr->type != NC_RESOURCE_KERNEL && vbr->type != NC_RESOURCE_RAMDISK && vbr->type != NC_RESOURCE_IMAGE) continue; if (vbr->type == NC_RESOURCE_IMAGE) emi_vbr = vbr; memcpy(vm2->virtualBootRecord + (vm2->virtualBootRecordLen++), vbr, sizeof(virtualBootRecord)); } if (emi_vbr == NULL) { LOGERROR("[%s] failed to find EMI among VBR entries\n", instance->instanceId); goto out; } if (vbr_add_ascii("boot:none:104857600:ext3:sda2:none", vm2) != EUCA_OK) { LOGERROR("[%s] could not add a boot partition VBR entry\n", instance->instanceId); goto out; } if (vbr_parse(vm2, NULL) != EUCA_OK) { LOGERROR("[%s] could not parse the boot partition VBR entry\n", instance->instanceId); goto out; } // compute tree of dependencies sentinel = vbr_alloc_tree(vm2, // the struct containing the VBR TRUE, // we always make the disk bootable, for consistency TRUE, // make working copy of runtime-modifiable files is_migration_dest, // tree of an instance on the migration destination (instance->do_inject_key) ? (instance->keyName) : (NULL), // the SSH key instance->instanceId); // ID is for logging if (sentinel == NULL) { LOGERROR("[%s] failed to prepare backing for instance\n", instance->instanceId); goto out; } LOGDEBUG("disk size prior to tree implementation is = %lld\n", sentinel->deps[0]->size_bytes); long long right_disk_size = sentinel->deps[0]->size_bytes; sem_p(disk_sem); { // download/create/combine the dependencies rc = art_implement_tree(sentinel, work_bs, cache_bs, work_prefix, INSTANCE_PREP_TIMEOUT_USEC); } sem_v(disk_sem); if (rc != EUCA_OK) { LOGERROR("[%s] failed to implement backing for instance\n", instance->instanceId); goto out; } LOGDEBUG("[%s] created the initial bootable disk\n", instance->instanceId); /* option A starts */ assert(emi_vbr); assert(sentinel->deps[0]); strcpy(emi_vbr->guestDeviceName, "sda"); // switch 'sda1' to 'sda' now that we've built the disk //emi_vbr->sizeBytes = sentinel->deps[0]->size_bytes; // update the size to match the disk emi_vbr->sizeBytes = right_disk_size; // this is bad... LOGDEBUG("at boot disk creation time emi_vbr->sizeBytes = %lld\n", emi_vbr->sizeBytes); euca_strncpy(emi_vbr->id, sentinel->deps[0]->id, SMALL_CHAR_BUFFER_SIZE); // change to the ID of the disk if (vbr_parse(vm, NULL) != EUCA_OK) { LOGERROR("[%s] could not parse the boot partition VBR entry\n", instance->instanceId); goto out; } emi_vbr->locationType = NC_LOCATION_NONE; // i.e., it should already exist art_free(sentinel); /* option A end */ /* option B starts * memcpy(vm, vm2, sizeof(virtualMachine)); if (save_instance_struct(instance)) // update instance checkpoint now that the struct got updated goto out; ret = EUCA_OK; goto out; * option B ends */ } // compute tree of dependencies sentinel = vbr_alloc_tree(vm, // the struct containing the VBR FALSE, // if image had to be made bootable, that was done above TRUE, // make working copy of runtime-modifiable files is_migration_dest, // tree of an instance on the migration destination (instance->do_inject_key) ? (instance->keyName) : (NULL), // the SSH key instance->instanceId); // ID is for logging if (sentinel == NULL) { LOGERROR("[%s] failed to prepare extended backing for instance\n", instance->instanceId); goto out; } sem_p(disk_sem); { // download/create/combine the dependencies rc = art_implement_tree(sentinel, work_bs, cache_bs, work_prefix, INSTANCE_PREP_TIMEOUT_USEC); } sem_v(disk_sem); if (rc != EUCA_OK) { LOGERROR("[%s] failed to implement backing for instance\n", instance->instanceId); goto out; } if (save_instance_struct(instance)) // update instance checkpoint now that the struct got updated goto out; ret = EUCA_OK; out: if (sentinel) art_free(sentinel); return (ret); }
//! //! Implement the backing store for a given instance //! //! @param[in] instance pointer to the instance //! @param[in] is_migration_dest //! //! @return EUCA_OK on success or EUCA_ERROR on failure //! //! @pre The instance parameter must not be NULL. //! //! @post //! int create_instance_backing(ncInstance * instance, boolean is_migration_dest) { int rc = 0; int ret = EUCA_ERROR; virtualMachine *vm = &(instance->params); artifact *sentinel = NULL; char work_prefix[1024] = { 0 }; // {userId}/{instanceId} char base_path[EUCA_MAX_PATH]; char user_dir_path[EUCA_MAX_PATH]; // set various instance-directory-relative paths in the instance struct set_instance_paths(instance); set_path(base_path, sizeof(base_path), NULL, NULL); snprintf(user_dir_path, sizeof(user_dir_path), "%s/%s", base_path, instance->userId); // create backing directory if ((check_path(user_dir_path) == 1) && (mkdir(user_dir_path, INSTANCE_DIRECTORY_PERM) == -1)) { LOGERROR("[%s] could not create backing directory %s\n", instance->instanceId, user_dir_path); goto out; } if (mkdir(instance->instancePath, INSTANCE_DIRECTORY_PERM) == -1) { LOGERROR("[%s] could not create backing directory %s\n", instance->instanceId, instance->instancePath); goto out; } if (strstr(instance->platform, "windows")) { // generate the floppy file for windows instances if (makeWindowsFloppy(nc_state.home, instance->instancePath, instance->keyName, instance->instanceId)) { LOGERROR("[%s] could not create windows bootup script floppy\n", instance->instanceId); goto out; } else { set_path(instance->floppyFilePath, sizeof(instance->floppyFilePath), instance, "floppy"); instance->hasFloppy = TRUE; } } else if (instance->credential && strlen(instance->credential)) { LOGDEBUG("[%s] creating floppy for instance credential\n", instance->instanceId); if (make_credential_floppy(nc_state.home, instance->instancePath, instance->credential)) { LOGERROR("[%s] could not create credential floppy\n", instance->instanceId); goto out; } else { set_path(instance->floppyFilePath, sizeof(instance->floppyFilePath), instance, "floppy"); instance->hasFloppy = TRUE; } } else if(instance->hasFloppy && is_migration_dest) { LOGDEBUG("[%s] creating blank instance credential floppy\n", instance->instanceId); char dest_path[1024] = ""; int fd = 0; snprintf(dest_path, 1024, "%s/floppy", instance->instancePath); if ((fd = open(dest_path, O_CREAT | O_TRUNC | O_RDWR, 0700)) < 0) { LOGERROR("[%s] failed to create fake floppy\n", instance->instanceId); goto out; } else { lseek(fd, 1024*2048-1, SEEK_SET); write(fd, "\n", 1); } close(fd); } else { instance->hasFloppy = FALSE; } set_id(instance, NULL, work_prefix, sizeof(work_prefix)); // compute tree of dependencies sentinel = vbr_alloc_tree(vm, // the struct containing the VBR TRUE, // make working copy of runtime-modifiable files is_migration_dest, // tree of an instance on the migration destination (instance->do_inject_key) ? (instance->keyName) : (NULL), // the SSH key &(instance->bail_flag), // flag indicating that provisioning should bail instance->instanceId); // ID is for logging if (sentinel == NULL) { LOGERROR("[%s] failed to prepare extended backing for instance\n", instance->instanceId); goto out; } sem_p(disk_sem); { // download/create/combine the dependencies rc = art_implement_tree(sentinel, work_bs, cache_bs, work_prefix, INSTANCE_PREP_TIMEOUT_USEC); } sem_v(disk_sem); if (rc != EUCA_OK) { LOGERROR("[%s] failed to implement backing for instance\n", instance->instanceId); goto out; } // copy EBS entries from VBR[] to volumes[] for (int i = 0; ((i < EUCA_MAX_VBRS) && (i < instance->params.virtualBootRecordLen)); i++) { virtualBootRecord *vbr = &(instance->params.virtualBootRecord[i]); if (vbr->locationType == NC_LOCATION_SC) { char *volumeId = vbr->id; // id is 'emi-XXXX', replace it with 'vol-XXXX' ebs_volume_data *vol_data = NULL; if (deserialize_volume(vbr->resourceLocation, &vol_data) == 0) { volumeId = vol_data->volumeId; } if (save_volume(instance, volumeId, vbr->resourceLocation, // attachmentToken vbr->preparedResourceLocation, // connect_string vbr->guestDeviceName, VOL_STATE_ATTACHED, vbr->backingPath) == NULL) { // the XML LOGERROR("[%s] failed to add record for volume %s\n", instance->instanceId, volumeId); } EUCA_FREE(vol_data); } } if (save_instance_struct(instance)) // update instance checkpoint now that the struct got updated goto out; ret = EUCA_OK; out: if (sentinel) art_free(sentinel); return (ret); }
//! //! Implement the backing store for a given instance //! //! @param[in] instance pointer to the instance //! @param[in] is_migration_dest //! //! @return EUCA_OK on success or EUCA_ERROR on failure //! //! @pre The instance parameter must not be NULL. //! //! @post //! int create_instance_backing(ncInstance * instance, boolean is_migration_dest) { int rc = 0; int ret = EUCA_ERROR; virtualMachine *vm = &(instance->params); artifact *sentinel = NULL; char work_prefix[1024] = { 0 }; // {userId}/{instanceId} // set various instance-directory-relative paths in the instance struct set_instance_paths(instance); // ensure instance directory exists if (ensure_directories_exist(instance->instancePath, 0, NULL, "root", BACKING_DIRECTORY_PERM) == -1) goto out; if (strstr(instance->platform, "windows")) { // generate the floppy file for windows instances if (makeWindowsFloppy(nc_state.home, instance->instancePath, instance->keyName, instance->instanceId)) { LOGERROR("[%s] could not create windows bootup script floppy\n", instance->instanceId); goto out; } else { set_path(instance->floppyFilePath, sizeof(instance->floppyFilePath), instance, "floppy"); } }else if (instance->instancePk != NULL && strlen(instance->instancePk) > 0) { // TODO: credential floppy is limited to Linux instances ATM LOGDEBUG("[%s] creating floppy for instance credential\n", instance->instanceId); if (make_credential_floppy(nc_state.home, instance)) { LOGERROR("[%s] could not create credential floppy\n", instance->instanceId); goto out; } else { set_path(instance->floppyFilePath, sizeof(instance->floppyFilePath), instance, "floppy"); } } set_id(instance, NULL, work_prefix, sizeof(work_prefix)); // compute tree of dependencies sentinel = vbr_alloc_tree(vm, // the struct containing the VBR FALSE, // for Xen and KVM we do not need to make disk bootable TRUE, // make working copy of runtime-modifiable files is_migration_dest, // tree of an instance on the migration destination (instance->do_inject_key) ? (instance->keyName) : (NULL), // the SSH key instance->instanceId); // ID is for logging if (sentinel == NULL) { LOGERROR("[%s] failed to prepare backing for instance\n", instance->instanceId); goto out; } sem_p(disk_sem); { // download/create/combine the dependencies rc = art_implement_tree(sentinel, work_bs, cache_bs, work_prefix, INSTANCE_PREP_TIMEOUT_USEC); } sem_v(disk_sem); if (rc != EUCA_OK) { LOGERROR("[%s] failed to implement backing for instance\n", instance->instanceId); goto out; } if (save_instance_struct(instance)) // update instance checkpoint now that the struct got updated goto out; ret = EUCA_OK; out: if (sentinel) art_free(sentinel); return (ret); }