//! //! Function description. //! //! @param[in] se //! //! @return //! //! @see //! //! @pre List of pre-conditions //! //! @post List of post conditions //! //! @note //! int se_execute(sequence_executor * se) { int i = 0; int rc = 0; int failed = 0; int lastran = 0; int ret = 0; char out[1024] = ""; char err[1024] = ""; if (!se || !se->init) { return (1); } ret = 0; failed = 0; for (i = 0; i < se->max_commands; i++) { LOGDEBUG("RUNNING COMMAND: command='%s'\n", se->commands[i]); rc = timeshell(se->commands[i], out, err, 1024, se->commands_timers[i] ? se->commands_timers[i] : se->default_timeout); lastran = i; if (se->checkers[i]) { rc = se->checkers[i] (rc, out, err); } if (rc) { LOGERROR("COMMAND FAILED: exitcode='%d' command='%s' stdout='%s' stderr='%s'\n", rc, se->commands[i], out, err); failed = 1; break; } else { LOGDEBUG("COMMAND SUCCESS: command='%s' stdout='%s' stderr='%s'\n", se->commands[i], out, err); } } if (se->clean_only_on_fail && failed) { for (i = lastran; i >= 0; i--) { if (se->cleanup_commands[i]) { LOGDEBUG("RUNNING CLEANUP_COMMAND: command='%s'\n", se->cleanup_commands[i]); rc = system(se->cleanup_commands[i]); rc = rc >> 8; } } }
//! //! //! //! @param[in] dev_string //! //! @return -1 for any failures, 0 if a timeout occured or a positive value is success. //! int disconnect_iscsi_target(const char *dev_string) { char command[MAX_PATH] = { 0 }; char stdout_str[MAX_OUTPUT] = { 0 }; char stderr_str[MAX_OUTPUT] = { 0 }; int ret = 0; assert(strlen(home)); snprintf(command, MAX_PATH, "%s %s,%s", disconnect_storage_cmd_path, home, dev_string); LOGTRACE("invoking `%s`\n", command); sem_p(iscsi_sem); ret = timeshell(command, stdout_str, stderr_str, MAX_OUTPUT, DISCONNECT_TIMEOUT); sem_v(iscsi_sem); LOGDEBUG("disconnect script returned: %d, stdout: '%s', stderr: '%s'\n", ret, stdout_str, stderr_str); return (ret); }
//! //! //! //! @param[in] dev_string //! //! @return a pointer //! char *get_iscsi_target(const char *dev_string) { char command[MAX_PATH] = { 0 }; char stdout_str[MAX_OUTPUT] = { 0 }; char stderr_str[MAX_OUTPUT] = { 0 }; int ret = 0; assert(strlen(home)); snprintf(command, MAX_PATH, "%s %s,%s", get_storage_cmd_path, home, dev_string); LOGDEBUG("invoking `%s`\n", command); sem_p(iscsi_sem); ret = timeshell(command, stdout_str, stderr_str, MAX_OUTPUT, GET_TIMEOUT); sem_v(iscsi_sem); LOGDEBUG("get storage script returned: %d, stdout: '%s', stderr: '%s'\n", ret, stdout_str, stderr_str); if (ret == 0) return (strdup(stdout_str)); return (NULL); }
//! //! 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; }