Ejemplo n.º 1
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;
}
Ejemplo n.º 2
0
//!
//! Connects an EBS volume to the local host as an ISCSI block device. The resulting device is placed in *result_device
//!
//! @param[in] sc_url - The URL to reach the cluster's SC at.
//! @param[in] attachment_token - The attachment token/volume string received in the attach request (or vbr)
//! @param[in] use_ws_sec - Boolean to use WS-SEC on SC call.
//! @param[in] ws_sec_policy_file - Policy file for WS-SEC on SC call.
//! @param[in] local_ip - External IP of the local host. Will be used to send to SC for authorization
//! @param[in] local_iqn - IQN of local host for sending to SC for authorization.
//! @param[out] result_device - The block device that is the EBS volume connected to local host, will be populated on success.
//! @param[out] vol_data - The populated ebs_volume_data struct that hold volume info (id, connect string, token, etc)
//!
//! @return EUCA_OK on success, EUCA_ERROR on failure.
//!
//! @pre
//!
//! @post
//!
//! @note
//!
int connect_ebs_volume(char *sc_url, char *attachment_token, int use_ws_sec, char *ws_sec_policy_file, char *local_ip, char *local_iqn, char **result_device,
                       ebs_volume_data ** vol_data)
{
    int ret = EUCA_OK;
    char *reencrypted_token = NULL;
    char *connect_string = NULL;
    char *dev = NULL;
    int do_rescan = 1;

    if (sc_url == NULL || strlen(sc_url) == 0 || attachment_token == NULL || local_ip == NULL || local_iqn == NULL) {
        LOGERROR("Cannont connect ebs volume. Got NULL input parameters.\n");
        return EUCA_ERROR;
    }

    if (deserialize_volume(attachment_token, vol_data) != EUCA_OK || *vol_data == NULL) {
        LOGERROR("Failed parsing volume string %s\n", attachment_token);
        ret = EUCA_ERROR;
        return ret;
    }

    if (strlen((*vol_data)->volumeId) == 0 || (*vol_data)->token == NULL || strlen((*vol_data)->token) == 0) {
        LOGERROR("After deserializing volume string, still found null or empty volumeId or token");
        ret = EUCA_ERROR;
        return ret;
    }

    LOGTRACE("Parsed volume info: volumeId=%s, encrypted token=%s\n", (*vol_data)->volumeId, (*vol_data)->token);
    if (re_encrypt_token((*vol_data)->token, &reencrypted_token) != EUCA_OK || reencrypted_token == NULL || strlen(reencrypted_token) <= 0) {
        LOGERROR("Failed on re-encryption of token for call to SC\n");
        if (reencrypted_token != NULL) {
            EUCA_FREE(reencrypted_token);
        }
        return EUCA_ERROR;
    }

    LOGTRACE("Requesting volume lock\n");
    sem_p(vol_sem);                    //Acquire the lock, after this, failure requires 'goto release' for release of lock
    LOGTRACE("Got volume lock\n");

    LOGTRACE("Calling ExportVolume on SC at %s\n", sc_url);
    threadCorrelationId* corr_id = get_corrid();
    if (scClientCall(corr_id!=NULL ? corr_id->correlation_id: NULL, NULL, use_ws_sec, ws_sec_policy_file, request_timeout_sec, sc_url, "ExportVolume", (*vol_data)->volumeId, reencrypted_token, local_ip, local_iqn,
                     &connect_string) != EUCA_OK) {
        LOGERROR("Failed to get connection information for volume %s from storage controller at: %s\n", (*vol_data)->volumeId, sc_url);
        ret = EUCA_ERROR;
        goto release;
    } else {
        if (euca_strncpy((*vol_data)->connect_string, connect_string, EBS_CONNECT_STRING_MAX_LENGTH) == NULL) {
            LOGERROR("Failed to copy connect string from SC response: %s\n", connect_string);
            ret = EUCA_ERROR;
            goto release;
        }
    }

    //copy the connection info from the SC return to the resourceLocation.
    dev = connect_iscsi_target((*vol_data)->connect_string);
    if (!dev || !strstr(dev, "/dev")) {
        LOGERROR("Failed to connect to iSCSI target: %s\n", (*vol_data)->connect_string);
        //disconnect the volume
        if (cleanup_volume_attachment(sc_url, use_ws_sec, ws_sec_policy_file, (*vol_data), (*vol_data)->connect_string, local_ip, local_iqn, do_rescan) != EUCA_OK) {
            LOGTRACE("cleanup_volume_attachment returned failure on cleanup from connection failure\n");
        }
        ret = EUCA_ERROR;
        goto release;
    }

    *result_device = dev;

release:
    LOGTRACE("Releasing volume lock\n");
    sem_v(vol_sem);
    LOGTRACE("Released volume lock\n");

    if (reencrypted_token != NULL) {
        EUCA_FREE(reencrypted_token);
    }

    if (ret != EUCA_OK && (*vol_data) != NULL) {
        //Free the vol data struct too
        EUCA_FREE(*vol_data);
    }

    return ret;
}