Beispiel #1
0
static int
libvirt_reboot(const char *vm_name, const char *src, uint32_t seqno, void *priv)
{
	struct libvirt_info *info = (struct libvirt_info *)priv;
	virDomainPtr vdp = NULL, nvdp;
	virDomainInfo vdi;
	char *domain_desc;
	virConnectPtr vcp = NULL;
	virDomainPtr (*virt_lookup_fn)(virConnectPtr, const char *);
	int ret;
	int i;

	dbg_printf(5, "ENTER %s %s %u\n", __FUNCTION__, vm_name, seqno);
	VALIDATE(info);

	if (is_uuid(vm_name))
		virt_lookup_fn = virDomainLookupByUUIDString;
	else
		virt_lookup_fn = virDomainLookupByName;

	for (i = 0 ; i < info->vp_count ; i++) {
		vdp = virt_lookup_fn(info->vp[i], vm_name);
		if (vdp) {
			vcp = info->vp[i];
			break;
		}
	}

	if (!vdp || !vcp) {
		dbg_printf(2,
			"[libvirt:REBOOT] Nothing to do - domain %s does not exist\n",
			vm_name);
		return 1;
	}

	if (virDomainGetInfo(vdp, &vdi) == 0 && vdi.state == VIR_DOMAIN_SHUTOFF) {
		dbg_printf(2, "[libvirt:REBOOT] Nothing to do - domain %s is off\n",
			vm_name);
		virDomainFree(vdp);
		return 0;
	}

	syslog(LOG_NOTICE, "Rebooting domain %s\n", vm_name);
	dbg_printf(5, "[libvirt:REBOOT] Rebooting domain %s...\n", vm_name);

	domain_desc = virDomainGetXMLDesc(vdp, 0);

	if (!domain_desc) {
		dbg_printf(5, "[libvirt:REBOOT] Failed getting domain description "
			"from libvirt for %s...\n", vm_name);
	}

	dbg_printf(2, "[libvirt:REBOOT] Calling virDomainDestroy(%p) for %s\n",
		vdp, vm_name);

	ret = virDomainDestroy(vdp);
	if (ret < 0) {
		dbg_printf(2,
			"[libvirt:REBOOT] virDomainDestroy() failed for %s: %d/%d\n",
			vm_name, ret, errno);

		if (domain_desc)
			free(domain_desc);
		virDomainFree(vdp);
		return 1;
	}

	ret = wait_domain(vm_name, vcp, 15);

	if (ret) {
		syslog(LOG_NOTICE, "Domain %s still exists; fencing failed\n", vm_name);
		dbg_printf(2,
			"[libvirt:REBOOT] Domain %s still exists; fencing failed\n",
			vm_name);

		if (domain_desc)
			free(domain_desc);
		virDomainFree(vdp);
		return 1;
	}

	if (!domain_desc)
		return 0;

	/* 'on' is not a failure */
	ret = 0;

	dbg_printf(3, "[[ XML Domain Info ]]\n");
	dbg_printf(3, "%s\n[[ XML END ]]\n", domain_desc);

	dbg_printf(2, "[libvirt:REBOOT] Calling virDomainCreateLinux() for %s\n",
		vm_name);

	nvdp = virDomainCreateLinux(vcp, domain_desc, 0);
	if (nvdp == NULL) {
		/* More recent versions of libvirt or perhaps the
		 * KVM back-end do not let you create a domain from
		 * XML if there is already a defined domain description
		 * with the same name that it knows about.  You must
		 * then call virDomainCreate() */
		dbg_printf(2,
			"[libvirt:REBOOT] virDomainCreateLinux() failed for %s; "
			"Trying virDomainCreate()\n",
			vm_name);

		if (virDomainCreate(vdp) < 0) {
			syslog(LOG_NOTICE, "Could not restart %s\n", vm_name);
			dbg_printf(1, "[libvirt:REBOOT] Failed to recreate guest %s!\n",
				vm_name);
		}
	}

	free(domain_desc);
	virDomainFree(vdp);
	return ret;
}
Beispiel #2
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 = ((ncInstance *) arg);
    ncInstance *instance = NULL;
    struct nc_state_t *nc = NULL;
    virDomainPtr dom = NULL;
    virConnectPtr conn = NULL;
    rebooting_thread_params *params = ((rebooting_thread_params *) arg);
    instance = &(params->instance);
    nc = &(params->nc);

    LOGDEBUG("[%s] spawning rebooting thread\n", instance->instanceId);

    if ((conn = lock_hypervisor_conn()) == NULL) {
        LOGERROR("[%s] cannot connect to hypervisor to restart instance, giving up\n", instance->instanceId);
        EUCA_FREE(params);
        return NULL;
    }
    dom = virDomainLookupByName(conn, instance->instanceId);
    if (dom == NULL) {
        LOGERROR("[%s] cannot locate instance to reboot, giving up\n", instance->instanceId);
        unlock_hypervisor_conn();
        EUCA_FREE(params);
        return NULL;
    }
    // obtain the most up-to-date XML for domain from libvirt
    xml = virDomainGetXMLDesc(dom, 0);
    if (xml == NULL) {
        LOGERROR("[%s] cannot obtain metadata for instance to reboot, giving up\n", instance->instanceId);
        virDomainFree(dom);            // release libvirt resource
        unlock_hypervisor_conn();
        EUCA_FREE(params);
        return NULL;
    }
    virDomainFree(dom);                // release libvirt resource
    unlock_hypervisor_conn();

    // try shutdown first, then kill it if uncooperative
    if (shutdown_then_destroy_domain(instance->instanceId, TRUE) != EUCA_OK) {
        LOGERROR("[%s] failed to shutdown and destroy the instance to reboot, giving up\n", instance->instanceId);
        EUCA_FREE(params);
        return NULL;
    }
    // Add a shift to values of three of the metrics: ones that
    // drop back to zero after a reboot. The shift, which is based
    // on the latest value, ensures that values sent upstream do
    // not go backwards .
    sensor_shift_metric(instance->instanceId, "CPUUtilization");
    sensor_shift_metric(instance->instanceId, "NetworkIn");
    sensor_shift_metric(instance->instanceId, "NetworkOut");

    if ((conn = lock_hypervisor_conn()) == NULL) {
        LOGERROR("[%s] cannot connect to hypervisor to restart instance, giving up\n", instance->instanceId);
        EUCA_FREE(params);
        return NULL;
    }
    // domain is now shut down, create a new one with the same XML
    LOGINFO("[%s] rebooting\n", instance->instanceId);
    if (!strcmp(nc->pEucaNet->sMode, NETMODE_VPCMIDO)) {
        // need to sleep to allow midolman to update the VM interface
        sleep(10);
    }
    dom = virDomainCreateLinux(conn, xml, 0);
    if (dom == NULL) {
        LOGERROR("[%s] failed to restart instance\n", instance->instanceId);
        change_state(instance, SHUTOFF);
    } else {
        euca_strncpy(resourceName[0], instance->instanceId, MAX_SENSOR_NAME_LEN);
        sensor_refresh_resources(resourceName, resourceAlias, 1);   // refresh stats so we set base value accurately
        virDomainFree(dom);

        if (!strcmp(nc->pEucaNet->sMode, NETMODE_VPCMIDO)) {
            char iface[16], cmd[EUCA_MAX_PATH], obuf[256], ebuf[256], sPath[EUCA_MAX_PATH];
            int rc;
            snprintf(iface, 16, "vn_%s", instance->instanceId);
            
            // If this device does not have a 'brport' path, this isn't a bridge device
            snprintf(sPath, EUCA_MAX_PATH, "/sys/class/net/%s/brport/", iface);
            if (!check_directory(sPath)) {
                LOGDEBUG("[%s] removing instance interface %s from host bridge\n", instance->instanceId, iface);
                snprintf(cmd, EUCA_MAX_PATH, "%s brctl delif %s %s", nc->rootwrap_cmd_path, instance->params.guestNicDeviceName, iface);
                rc = timeshell(cmd, obuf, ebuf, 256, 10);
                if (rc) {
                    LOGERROR("unable to remove instance interface from bridge after launch: instance will not be able to connect to midonet (will not connect to network): check bridge/libvirt/kvm health\n");
                }
            }

            // Repeat process for secondary interfaces as well
            for (int i=0; i < EUCA_MAX_NICS; i++) {
                if (strlen(instance->secNetCfgs[i].interfaceId) == 0)
                    continue;

                snprintf(iface, 16, "vn_%s", instance->secNetCfgs[i].interfaceId);

                // If this device does not have a 'brport' path, this isn't a bridge device
                snprintf(sPath, EUCA_MAX_PATH, "/sys/class/net/%s/brport/", iface);
                if (!check_directory(sPath)) {
                    LOGDEBUG("[%s] removing instance interface %s from host bridge\n", instance->instanceId, iface);
                    snprintf(cmd, EUCA_MAX_PATH, "%s brctl delif %s %s", nc->rootwrap_cmd_path, instance->params.guestNicDeviceName, iface);
                    rc = timeshell(cmd, obuf, ebuf, 256, 10);
                    if (rc) {
                        LOGERROR("unable to remove instance interface from bridge after launch: instance will not be able to connect to midonet (will not connect to network): check bridge/libvirt/kvm health\n");
                    }
                }
            }
        }

    }
    EUCA_FREE(xml);

    unlock_hypervisor_conn();
    unset_corrid(get_corrid());
    EUCA_FREE(params);
    return NULL;
}
Beispiel #3
0
//!
//! Defines the thread that does the actual reboot of an instance.
//!
//! @param[in] arg a transparent pointer to the argument passed to this thread handler
//!
//! @return Always return NULL
//!
static void *rebooting_thread(void *arg)
{
#define REATTACH_RETRIES      3

    int i = 0;
    int err = 0;
    int error = 0;
    int rc = 0;
    int log_level_for_devstring = EUCATRACE;
    char *xml = NULL;
    char *remoteDevStr = NULL;
    char path[MAX_PATH] = "";
    char lpath[MAX_PATH] = "";
    char resourceName[1][MAX_SENSOR_NAME_LEN] = { {0} };
    char resourceAlias[1][MAX_SENSOR_NAME_LEN] = { {0} };
    ncVolume *volume = NULL;
    ncInstance *instance = ((ncInstance *) arg);
    virDomainPtr dom = NULL;
    virConnectPtr *conn = NULL;

    logprintfl(EUCADEBUG, "[%s] spawning rebooting thread\n", instance->instanceId);
    if ((xml = file2str(instance->libvirtFilePath)) == NULL) {
        logprintfl(EUCAERROR, "[%s] cannot obtain instance XML file %s\n", instance->instanceId, instance->libvirtFilePath);
        return NULL;
    }

    if ((conn = check_hypervisor_conn()) == NULL) {
        logprintfl(EUCAERROR, "[%s] cannot restart instance %s, abandoning it\n", instance->instanceId, instance->instanceId);
        change_state(instance, SHUTOFF);
        EUCA_FREE(xml);
        return NULL;
    }

    sem_p(hyp_sem);
    {
        dom = virDomainLookupByName(*conn, instance->instanceId);
    }
    sem_v(hyp_sem);

    if (dom == NULL) {
        EUCA_FREE(xml);
        return NULL;
    }

    sem_p(hyp_sem);
    {
        // for KVM, must stop and restart the instance
        logprintfl(EUCADEBUG, "[%s] destroying domain\n", instance->instanceId);
        error = virDomainDestroy(dom);  // @todo change to Shutdown? is this synchronous?
        virDomainFree(dom);
    }
    sem_v(hyp_sem);

    if (error) {
        EUCA_FREE(xml);
        return NULL;
    }
    // Add a shift to values of three of the metrics: ones that
    // drop back to zero after a reboot. The shift, which is based
    // on the latest value, ensures that values sent upstream do
    // not go backwards .
    sensor_shift_metric(instance->instanceId, "CPUUtilization");
    sensor_shift_metric(instance->instanceId, "NetworkIn");
    sensor_shift_metric(instance->instanceId, "NetworkOut");

    // domain is now shut down, create a new one with the same XML
    sem_p(hyp_sem);
    {
        logprintfl(EUCAINFO, "[%s] rebooting\n", instance->instanceId);
        dom = virDomainCreateLinux(*conn, xml, 0);
    }
    sem_v(hyp_sem);
    EUCA_FREE(xml);

    euca_strncpy(resourceName[0], instance->instanceId, MAX_SENSOR_NAME_LEN);
    sensor_refresh_resources(resourceName, resourceAlias, 1);   // refresh stats so we set base value accurately

    // re-attach each volume previously attached
    for (i = 0; i < EUCA_MAX_VOLUMES; ++i) {
        volume = &instance->volumes[i];
        if (strcmp(volume->stateName, VOL_STATE_ATTACHED) && strcmp(volume->stateName, VOL_STATE_ATTACHING))
            continue;           // skip the entry unless attached or attaching

        logprintfl(EUCADEBUG, "[%s] volumes [%d] = '%s'\n", instance->instanceId, i, volume->stateName);

        // get credentials, decrypt them
        remoteDevStr = get_iscsi_target(volume->remoteDev);
        if (!remoteDevStr || !strstr(remoteDevStr, "/dev")) {
            logprintfl(EUCAERROR, "[%s] failed to get local name of host iscsi device when re-attaching\n", instance->instanceId);
            rc = 1;
        } else {
            // set the path
            snprintf(path, sizeof(path), EUCALYPTUS_VOLUME_XML_PATH_FORMAT, instance->instancePath, volume->volumeId);  // vol-XXX.xml
            snprintf(lpath, sizeof(lpath), EUCALYPTUS_VOLUME_LIBVIRT_XML_PATH_FORMAT, instance->instancePath, volume->volumeId);    // vol-XXX-libvirt.xml

            // read in libvirt XML, which may have been modified by the hook above
            if ((xml = file2str(lpath)) == NULL) {
                logprintfl(EUCAERROR, "[%s][%s] failed to read volume XML from %s\n", instance->instanceId, volume->volumeId, lpath);
                rc = 1;
            }
        }

        EUCA_FREE(remoteDevStr);

        if (!rc) {
            // zhill - wrap with retry in case libvirt is dumb.
            err = 0;
            for (i = 1; i < REATTACH_RETRIES; i++) {
                // protect libvirt calls because we've seen problems during concurrent libvirt invocations
                sem_p(hyp_sem);
                {
                    err = virDomainAttachDevice(dom, xml);
                }
                sem_v(hyp_sem);

                if (err) {
                    logprintfl(EUCAERROR, "[%s][%s] failed to reattach volume (attempt %d of %d)\n", instance->instanceId, volume->volumeId, i,
                               REATTACH_RETRIES);
                    logprintfl(EUCADEBUG, "[%s][%s] error from virDomainAttachDevice: %d xml: %s\n", instance->instanceId, volume->volumeId, err,
                               xml);
                    sleep(3);   // sleep a bit and retry
                } else {
                    logprintfl(EUCAINFO, "[%s][%s] volume reattached as '%s'\n", instance->instanceId, volume->volumeId, volume->localDevReal);
                    break;
                }
            }

            log_level_for_devstring = EUCATRACE;
            if (err)
                log_level_for_devstring = EUCADEBUG;
            logprintfl(log_level_for_devstring, "[%s][%s] remote device string: %s\n", instance->instanceId, volume->volumeId, volume->remoteDev);
        }

        EUCA_FREE(xml);
    }

    if (dom == NULL) {
        logprintfl(EUCAERROR, "[%s] failed to restart instance\n", instance->instanceId);
        change_state(instance, SHUTOFF);
        return NULL;
    }

    sem_p(hyp_sem);
    {
        virDomainFree(dom);
    }
    sem_v(hyp_sem);
    return NULL;

#undef REATTACH_RETRIES
}
Beispiel #4
0
//!
//!
//!
//! @param[in] arg
//!
//! @return Always returns NULL
//!
static void *startup_thread(void *arg)
{
    int fd = 0;
    int iter = 0;
    long long tid = (*(long long *)arg);
    virDomainPtr dom = NULL;
    char file_name[1024] = { 0 };
    char xml[4096] = { 0 };
    char *xml_template =
        "<?xml version='1.0' encoding='UTF-8'?>"
        "<domain type='kvm'>"
        "  <name>tortura-%04lld</name>"
        "  <description>Eucalyptus instance i-XXX</description>"
        "  <os>"
        "    <type>hvm</type>"
        "  </os>"
        "  <features>"
        "    <acpi/>"
        "  </features>"
        "  <clock offset='localtime'/>"
        "  <on_poweroff>destroy</on_poweroff>"
        "  <on_reboot>restart</on_reboot>"
        "  <on_crash>destroy</on_crash>"
        "  <vcpu>1</vcpu>"
        "  <memory>52428</memory>"
        "  <devices>" "    <disk device='disk'>" "      <source file='%s'/>" "      <target bus='virtio' dev='vda'/>" "    </disk>" "  </devices>" "</domain>";

    snprintf(file_name, sizeof(file_name), "%s/%s-%lld", get_current_dir_name(), DUMMY_DISK_FILE, tid);

    umask(0000);
    if ((fd = open(file_name, O_RDWR | O_CREAT | O_TRUNC, 0666)) < 0) {
        printf("failed to create %s\n", DUMMY_DISK_FILE);
        perror("libvirt_tortura");
        exit(1);
    }

    if (lseek(fd, DUMMY_DISK_SIZE_BYTES, SEEK_SET) == ((off_t) - 1)) {
        printf("failed to seek in %s\n", DUMMY_DISK_FILE);
        perror("libvirt_tortura");
        exit(1);
    }

    if (write(fd, "x", 1) != 1) {
        printf("failed to write to %s\n", DUMMY_DISK_FILE);
        perror("libvirt_tortura");
        exit(1);
    }

    close(fd);

    sync();

    check_hypervisor_conn();
    for (iter = 0; iter < SITERS; iter++) {
        printf("startup thread %lld starting iteration %d\n", tid, iter);
        snprintf(xml, sizeof(xml), xml_template, tid, file_name);

        pthread_mutex_lock(&check_mutex);
        {
            dom = virDomainCreateLinux(conn, xml, 0);
        }
        pthread_mutex_unlock(&check_mutex);

        sleep(3);

        if (dom == NULL) {
            printf("ERROR: failed to start domain\n");
            continue;
        }

        pthread_mutex_lock(&check_mutex);
        {
            virDomainDestroy(dom);
            virDomainFree(dom);
            dom = NULL;
        }
        pthread_mutex_unlock(&check_mutex);
    }

    unlink(file_name);

    return (NULL);
}
Beispiel #5
0
void *startup_thread (void * arg)
{
    ncInstance * instance = (ncInstance *)arg;
    virDomainPtr dom = NULL;
    char *disk_path=NULL, *xml=NULL;
    char *brname=NULL;
    int error, i;
    
    if (! check_hypervisor_conn ()) {
        logprintfl (EUCAFATAL, "could not start instance %s, abandoning it\n", instance->instanceId);
        change_state (instance, SHUTOFF);
        return NULL;
    }
    
    error = vnetStartNetwork (nc_state.vnetconfig, instance->ncnet.vlan, NULL, NULL, &brname);
    if ( error ) {
        logprintfl (EUCAFATAL, "start network failed for instance %s, terminating it\n", instance->instanceId);
        change_state (instance, SHUTOFF);
        return NULL;
    }
    logprintfl (EUCAINFO, "network started for instance %s\n", instance->instanceId);
    
    error = scMakeInstanceImage (nc_state.home, 
				 instance->userId, 
                                 instance->imageId, instance->imageURL, 
                                 instance->kernelId, instance->kernelURL, 
                                 instance->ramdiskId, instance->ramdiskURL, 
                                 instance->instanceId, instance->keyName, 
				 &disk_path, 
				 addkey_sem, nc_state.convert_to_disk,
				 instance->params.disk*1024);
    if (error) {
        logprintfl (EUCAFATAL, "Failed to prepare images for instance %s (error=%d)\n", instance->instanceId, error);
        change_state (instance, SHUTOFF);
	if (brname) free(brname);
        if (disk_path) free(disk_path);
        return NULL;
    }
    if (instance->state==TEARDOWN) { // timed out in STAGING
            if (disk_path) free(disk_path);
            if (brname) free(brname);
            return NULL;
    }
    if (instance->state==CANCELED) {
        logprintfl (EUCAFATAL, "Startup of instance %s was cancelled\n", instance->instanceId);
        change_state (instance, SHUTOFF);
	if (brname) free(brname);
        if (disk_path) free(disk_path);
        return NULL;
    }
    
    error = get_instance_xml (nc_state.gen_libvirt_cmd_path,
		              instance->userId, instance->instanceId, 
			      instance->ramdiskId,
			      instance->kernelId,
                              disk_path, 
                              &(instance->params), 
                              instance->ncnet.privateMac, 
                              brname,
                              nc_state.config_use_virtio_net,
                              nc_state.config_use_virtio_root,
                              &xml);

    if (brname) free(brname);
    if (disk_path) free(disk_path);
    if (xml) logprintfl (EUCADEBUG2, "libvirt XML config:\n%s\n", xml);
    if (error) {
        logprintfl (EUCAFATAL, "Failed to create libvirt XML config for instance %s\n", instance->instanceId);
        change_state (instance, SHUTOFF);
        return NULL;
    }
    
    scStoreStringToInstanceFile (instance->userId, instance->instanceId, "libvirt.xml", xml); /* for debugging */
    scSaveInstanceInfo(instance); /* to enable NC recovery */

    /* we serialize domain creation as hypervisors can get confused with
     * too many simultaneous create requests */
    logprintfl (EUCADEBUG2, "about to start domain %s\n", instance->instanceId);
    print_running_domains ();
    for (i=0; i<5 && dom == NULL; i++) {
      sem_p (hyp_sem);
      dom = virDomainCreateLinux (nc_state.conn, xml, 0);
      sem_v (hyp_sem);
    }
    if (xml) free(xml);
    if (dom == NULL) {
        logprintfl (EUCAFATAL, "hypervisor failed to start domain\n");
        change_state (instance, SHUTOFF);
        return NULL;
    }
    eventlog("NC", instance->userId, "", "instanceBoot", "begin"); // TODO: bring back correlationId
    
    sem_p(hyp_sem);
    virDomainFree(dom);
    sem_v(hyp_sem);

    sem_p (inst_sem);
    // check one more time for cancellation
    if (instance->state==TEARDOWN) { 
      // timed out in BOOTING
    } else if (instance->state==CANCELED || instance->state==SHUTOFF) {
      logprintfl (EUCAFATAL, "startup of instance %s was cancelled\n", instance->instanceId);
      change_state (instance, SHUTOFF);
    } else {
      logprintfl (EUCAINFO, "booting VM instance %s\n", instance->instanceId);
      instance->bootTime = time (NULL);
      change_state (instance, BOOTING);
    }
    sem_v (inst_sem);
    return NULL;
}
Beispiel #6
0
/* thread that does the actual reboot */
static void * rebooting_thread (void *arg) 
{
    virConnectPtr *conn;
    ncInstance * instance = (ncInstance *)arg;
    struct stat statbuf;
    int rc = 0;
    // RESTARTING,
           //     FAILED_RESTART,
           //     SUCCESS_RESTART
    logprintfl (EUCADEBUG, "{%u} spawning rebooting thread\n", (unsigned int)pthread_self());
    char * xml = file2str (instance->libvirtFilePath);
    if (xml == NULL) {
        logprintfl (EUCAERROR, "cannot obtain XML file %s\n", instance->libvirtFilePath);
        return NULL;
    }
 
    conn = check_hypervisor_conn();
    if (! conn) {
        logprintfl (EUCAERROR, "cannot restart instance %s, abandoning it\n", instance->instanceId);
        change_state (instance, SHUTOFF);
        free (xml);
        return NULL;
    }
    
    sem_p(inst_sem);
    change_task_state (instance, REBOOTING);
    copy_instances ();
    sem_v(inst_sem);
    
    sem_p (hyp_sem);
    virDomainPtr dom = virDomainLookupByName(*conn, instance->instanceId);
    sem_v (hyp_sem);
    if (dom == NULL) {
        free (xml);
       sem_p(inst_sem);
       change_task_state (instance, FAILED_REBOOT);
       sem_v(inst_sem);
        return NULL;
    }

    sem_p (hyp_sem);
    // for KVM, must stop and restart the instance
    int error = virDomainDestroy (dom); // TODO: change to Shutdown?  TODO: is this synchronous?
    virDomainFree(dom);
    sem_v (hyp_sem);

    if (error) {
        free (xml);
        sem_p(inst_sem);
       change_task_state (instance, FAILED_REBOOT);
       sem_v(inst_sem);
       
        return NULL;
    }
    
  #if 0 
    // domain is now shut down, create a new one with the same XML
    sem_p (hyp_sem); 
    dom = virDomainCreateLinux (*conn, xml, 0);
    sem_v (hyp_sem);
    free (xml);

    char *remoteDevStr=NULL;
    // re-attach each volume previously attached
    for (int i=0; i < EUCA_MAX_VOLUMES; ++i) {
        ncVolume * volume = &instance->volumes[i];
        if (strcmp (volume->stateName, VOL_STATE_ATTACHED) &&
            strcmp (volume->stateName, VOL_STATE_ATTACHING))
            continue; // skip the entry unless attached or attaching
        
        char attach_xml[1024];
        int rc;
        // get credentials, decrypt them
        remoteDevStr = get_iscsi_target (volume->remoteDev);
        if (!remoteDevStr || !strstr(remoteDevStr, "/dev")) {
            logprintfl(EUCAERROR, "Reattach-volume: failed to get local name of host iscsi device\n");
            rc = 1;
        } else {
            rc = gen_libvirt_attach_xml (volume->volumeId,
                                         instance, 
                                         volume->localDevReal, 
                                         remoteDevStr, 
                                         attach_xml, 
                                         sizeof(attach_xml));
        }

        if (remoteDevStr)
            free (remoteDevStr);

        if (!rc) {
            int err;
            sem_p (hyp_sem);
            err = virDomainAttachDevice (dom, attach_xml);
            sem_v (hyp_sem);      
            if (err) {
                logprintfl (EUCAERROR, "virDomainAttachDevice() failed (err=%d) XML=%s\n", err, attach_xml);
            } else {
                logprintfl (EUCAINFO, "reattached '%s' to '%s' in domain %s\n", volume->remoteDev, volume->localDevReal, instance->instanceId);
            }
        }
    }
  #endif

    int ret=restore_and_volume_instance(instance->instanceId);		//20130122-th
    if (ret==1) {
        logprintfl (EUCAERROR, "Failed to REBOOT instance %s\n", instance->instanceId);
        change_state (instance, SHUTOFF);
        sem_p(inst_sem);
        change_task_state (instance, FAILED_REBOOT);
        sem_v(inst_sem);
        return NULL;
    }
    
    sem_p(inst_sem);
    change_task_state (instance, SUCCESS_REBOOT);
    save_instance_struct (instance);
    copy_instances();
    sem_v (inst_sem);
    
    return NULL;
}
Beispiel #7
0
static int
libvirt_reboot(const char *vm_name, const char *src,
	       uint32_t seqno, void *priv)
{
	struct libvirt_info *info = (struct libvirt_info *)priv;
	virDomainPtr vdp, nvdp;
	virDomainInfo vdi;
	char *domain_desc;
	int ret;

	//uuid_unparse(vm_uuid, uu_string);
	dbg_printf(5, "%s %s\n", __FUNCTION__, vm_name);
	VALIDATE(info);
	
	if (is_uuid(vm_name)) {
		vdp = virDomainLookupByUUIDString(info->vp,
					    (const char *)vm_name);
	} else {
		vdp = virDomainLookupByName(info->vp, vm_name);
	}

	if (!vdp) {
		dbg_printf(2, "[libvirt:REBOOT] Nothing to "
			   "do - domain does not exist\n");
		return 1;
	}

	if (((virDomainGetInfo(vdp, &vdi) == 0) &&
	     (vdi.state == VIR_DOMAIN_SHUTOFF))) {
			dbg_printf(2, "[libvirt:REBOOT] Nothing to "
				   "do - domain is off\n");
		virDomainFree(vdp);
		return 0;
	}


	syslog(LOG_NOTICE, "Rebooting domain %s\n", vm_name);
	printf("Rebooting domain %s...\n", vm_name);
	domain_desc = virDomainGetXMLDesc(vdp, 0);

	if (!domain_desc) {
		printf("Failed getting domain description from "
		       "libvirt\n");
	}

	dbg_printf(2, "[REBOOT] Calling virDomainDestroy(%p)\n", vdp);
	ret = virDomainDestroy(vdp);
	if (ret < 0) {
		printf("virDomainDestroy() failed: %d/%d\n", ret, errno);
		free(domain_desc);
		virDomainFree(vdp);
		return 1;
	}

	ret = wait_domain(vm_name, info->vp, 15);

	if (ret) {
		syslog(LOG_NOTICE, "Domain %s still exists; fencing failed\n",
		       vm_name);
		printf("Domain %s still exists; fencing failed\n", vm_name);
		if (domain_desc)
			free(domain_desc);
		return 1;
	}
		
	if (!domain_desc)
		return 0;

	/* 'on' is not a failure */
	ret = 0;

	dbg_printf(3, "[[ XML Domain Info ]]\n");
	dbg_printf(3, "%s\n[[ XML END ]]\n", domain_desc);
	dbg_printf(2, "Calling virDomainCreateLinux()...\n");

	nvdp = virDomainCreateLinux(info->vp, domain_desc, 0);
	if (nvdp == NULL) {
		/* More recent versions of libvirt or perhaps the
		 * KVM back-end do not let you create a domain from
		 * XML if there is already a defined domain description
		 * with the same name that it knows about.  You must
		 * then call virDomainCreate() */
		dbg_printf(2, "Failed; Trying virDomainCreate()...\n");
		if (virDomainCreate(vdp) < 0) {
			syslog(LOG_NOTICE,
			       "Could not restart %s\n",
			       vm_name);
			dbg_printf(1, "Failed to recreate guest"
				   " %s!\n", vm_name);
		}
	}

	free(domain_desc);

	return ret;
}
Beispiel #8
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 = ((ncInstance *) arg);
    virDomainPtr dom = NULL;
    virConnectPtr conn = NULL;

    LOGDEBUG("[%s] spawning rebooting thread\n", instance->instanceId);

    if ((conn = lock_hypervisor_conn()) == NULL) {
        LOGERROR("[%s] cannot connect to hypervisor to restart instance, giving up\n", instance->instanceId);
        return NULL;
    }
    dom = virDomainLookupByName(conn, instance->instanceId);
    if (dom == NULL) {
        LOGERROR("[%s] cannot locate instance to reboot, giving up\n", instance->instanceId);
        unlock_hypervisor_conn();
        return NULL;
    }
    // obtain the most up-to-date XML for domain from libvirt
    xml = virDomainGetXMLDesc(dom, 0);
    if (xml == NULL) {
        LOGERROR("[%s] cannot obtain metadata for instance to reboot, giving up\n", instance->instanceId);
        virDomainFree(dom);            // release libvirt resource
        unlock_hypervisor_conn();
        return NULL;
    }
    virDomainFree(dom);                // release libvirt resource
    unlock_hypervisor_conn();

    // try shutdown first, then kill it if uncooperative
    if (shutdown_then_destroy_domain(instance->instanceId, TRUE) != EUCA_OK) {
        LOGERROR("[%s] failed to shutdown and destroy the instance to reboot, giving up\n", instance->instanceId);
        return NULL;
    }
    // Add a shift to values of three of the metrics: ones that
    // drop back to zero after a reboot. The shift, which is based
    // on the latest value, ensures that values sent upstream do
    // not go backwards .
    sensor_shift_metric(instance->instanceId, "CPUUtilization");
    sensor_shift_metric(instance->instanceId, "NetworkIn");
    sensor_shift_metric(instance->instanceId, "NetworkOut");

    if ((conn = lock_hypervisor_conn()) == NULL) {
        LOGERROR("[%s] cannot connect to hypervisor to restart instance, giving up\n", instance->instanceId);
        return NULL;
    }
    // domain is now shut down, create a new one with the same XML
    LOGINFO("[%s] rebooting\n", instance->instanceId);
    dom = virDomainCreateLinux(conn, xml, 0);
    if (dom == NULL) {
        LOGERROR("[%s] failed to restart instance\n", instance->instanceId);
        change_state(instance, SHUTOFF);
    } else {
        euca_strncpy(resourceName[0], instance->instanceId, MAX_SENSOR_NAME_LEN);
        sensor_refresh_resources(resourceName, resourceAlias, 1);   // refresh stats so we set base value accurately
        virDomainFree(dom);
    }
    EUCA_FREE(xml);

    unlock_hypervisor_conn();
    unset_corrid(get_corrid());
    return NULL;
}