/** * \brief To retrieve specific submission parameters * \param specificParamss The string containing the list of parameters */ void OpenNebulaServer::retrieveUserSpecificParams(const std::string& specificParams) { std::vector<std::string> listParams; boost::split(listParams, specificParams, boost::is_any_of(" ")); for (std::vector<std::string>::iterator it = listParams.begin(); it != listParams.end(); ++it) { size_t pos = it->find("="); if (pos != std::string::npos) { std::string param = it->substr(0, pos); std::string value = it->substr(pos+1, std::string::npos); if (param == "endpoint") { mcloudEndpoint = value; } else if (param == "user") { mcloudUser = value; } else if (param == "user-password") { mcloudUserPassword = value; } else if (param == "vm-image") { mvmImageId = value; } else if (param == "vm-user") { mvmUser = value; } else if (param == "vm-key") { mvmUserKey = value; } else if (param == "nfs-server") { mnfsServer = value; } else if (param == "nfs-mountpoint") { mnfsMountPoint = value; } else { throw TMSVishnuException(ERRCODE_INVALID_PARAM, param); } } } }
/** * @brief Return a string as expected by OpenNebula API (username:password) * @return string */ std::string OpenNebulaServer::getSessionString(void) { if (mcloudUser.empty() && mcloudUserPassword.empty()) { throw TMSVishnuException(ERRCODE_INVALID_PARAM, "Either the username or the password to authenticate against OpenNebula is empty"); } return boost::str(boost::format("%1%:%2%") % mcloudUser % mcloudUserPassword); }
int solveGenerique(diet_profile_t* pb) { std::string authKey; std::string machineId; std::string optionValueSerialized; std::string listSerialized = ""; //IN Parameters diet_string_get(pb,0, authKey); diet_string_get(pb,1, machineId); diet_string_get(pb,2, optionValueSerialized); // reset profile to handle result diet_profile_reset(pb, 2); QueryParameters* options = NULL; List* list = NULL; try { //To parse the object serialized if (! vishnu::parseEmfObject(optionValueSerialized, options)) { throw TMSVishnuException(ERRCODE_INVALID_PARAM); } QueryType query(authKey); //MAPPER CREATION Mapper *mapper = MapperRegistry::getInstance()->getMapper(vishnu::TMSMAPPERNAME); int mapperkey = mapper->code(query.getCommandName()); mapper->code(optionValueSerialized, mapperkey); std::string cmd = mapper->finalize(mapperkey); list = query.list(options); ::ecorecpp::serializer::serializer _ser; listSerialized = _ser.serialize_str(list); //OUT Parameter diet_string_set(pb,0, "success"); diet_string_set(pb,1, listSerialized); FINISH_COMMAND(authKey, cmd, vishnu::TMS, vishnu::CMDSUCCESS, ""); } catch (VishnuException& ex) { try { FINISH_COMMAND(authKey, "", vishnu::TMS, vishnu::CMDFAILED, ""); } catch (VishnuException& fe) { ex.appendMsgComp(fe.what()); } diet_string_set(pb,0, "error"); diet_string_set(pb,1, ex.what()); } delete options; delete list; return 0; }
/** * @brief Get the home directory of the currently logged user * @return A string, throw exception on error */ std::string vishnu::getCurrentUserHome(void) { struct passwd *pw = getpwuid(getuid()); if (! pw) { throw TMSVishnuException(ERRCODE_SYSTEM, boost::str(boost::format("getpwuid() failed with uid %1%") % getuid())); } return std::string(pw->pw_dir); }
/** * \brief Function for cleaning up virtual machine * \param vmId The id of the virtual machine */ void OpenNebulaServer::releaseResources(const std::string& vmId) { OneRPCManager rpcManager(mcloudEndpoint); rpcManager.setMethod("one.vm.action"); rpcManager.addParam(getSessionString()); rpcManager.addParam(std::string("delete")); rpcManager.addParam(vishnu::convertToInt(vmId)); rpcManager.execute(); if (! rpcManager.lastCallSucceeded()) { throw TMSVishnuException(ERRCODE_BATCH_SCHEDULER_ERROR, rpcManager.getStringResult()); } //FIXME: check that the vm is shutdown and clear it LOG(boost::str(boost::format("[INFO] VM deleted: %1%") % vmId), LogInfo); }
/** * \brief This function get the information about different cloud endpoint * \param queueName (optional) Queue name * \return The list of cloud information */ TMS_Data::ListQueues_ptr OpenNebulaServer::listQueues(const std::string& queueName) { OneCloudInstance cloud(mcloudEndpoint, getSessionString()); TMS_Data::ListQueues_ptr queues = new TMS_Data::ListQueues(); TMS_Data::Queue* queue = cloud.getQueueInfo(); if (! queue) { TMSVishnuException(ERRCODE_RUNTIME_ERROR, "Null queue info"); } queue->setName(queueName); queues->getQueues().push_back(queue); return queues; }
/** * @brief copy a given file to the current user home * @param path The file path * @return The resulting file path */ std::string vishnu::copyFileToUserHome(const std::string& path) { std::string result; try { bfs::path from(path); bfs::path to(boost::str(boost::format("%1%/%2%") % getCurrentUserHome() % bfs::basename(from))); bfs::copy_file(from, to, bfs::copy_option::overwrite_if_exists); result = to.native(); } catch (const boost::filesystem::filesystem_error ex) { throw TMSVishnuException(ERRCODE_SYSTEM, ex.what()); } return result; }
/** * \brief Function to submit a job * \param scriptPath the path to the script containing the job characteristique * \param options the options to submit job * \param job The job data structure * \param envp The list of environment variables used by submission function * \return raises an exception on error */ int OpenNebulaServer::submit(const std::string& scriptPath, const TMS_Data::SubmitOptions& options, TMS_Data::ListJobs& jobSteps, char** envp) { mjobId = vishnu::getVar("VISHNU_JOB_ID", false); mjobOutputDir = vishnu::getVar("VISHNU_OUTPUT_DIR", false); handleCloudInfo(options); setupJobDataDir(mjobId, scriptPath); replaceEnvVariables(scriptPath); OneRPCManager rpcManager(mcloudEndpoint); rpcManager.setMethod("one.vm.allocate"); rpcManager.addParam(getSessionString()); rpcManager.addParam(generateKvmTemplate(options)); rpcManager.addParam(false); // to create VM on pending state rpcManager.execute(); if (! rpcManager.lastCallSucceeded()) { throw TMSVishnuException(ERRCODE_BATCH_SCHEDULER_ERROR, rpcManager.getStringResult()); } TMS_Data::Job_ptr jobPtr = new TMS_Data::Job(); OneCloudInstance oneCloud(mcloudEndpoint, getSessionString()); VmT vmInfo; jobPtr->setVmId(vishnu::convertToString( rpcManager.getIntResult() )); if (oneCloud.loadVmInfo(vishnu::convertToInt(jobPtr->getVmId()), vmInfo) == 0) { jobPtr->setVmIp(vmInfo.ipAddr); } LOG(boost::str(boost::format("[INFO] Virtual machine created. ID: %1%, IP: %2%" ) % jobPtr->getVmId() % jobPtr->getVmIp()), LogInfo); //FIXME: job.setBatchJobId(vishnu::convertToString(jobPid)); jobPtr->setStatus(vishnu::STATE_SUBMITTED); jobPtr->setName(returnInputOrDefaultIfEmpty(options.getName(), "PID_"+jobPtr->getBatchJobId())); jobPtr->setOutputPath(mbaseDataDir+"/stdout"); jobPtr->setErrorPath(mbaseDataDir+"/stderr"); jobPtr->setNbNodes(1); jobPtr->setLocalAccount(mvmUser); jobSteps.getJobs().push_back(jobPtr); return 0; }
/** * \brief Function to retrieve an environment variable * \param name The name of the variable * \param optional tell whether the parameter is optional or not * \param defaultValue give the default value return when the variable is optional * \return the value of the environment variable or throw exception is the variable is set and is not optional */ std::string vishnu::getVar(const std::string& name, const bool & optional, const std::string defaultValue) { std::string value = defaultValue; char* cvalue = getenv(name.c_str()); if (cvalue != NULL) { value = std::string(cvalue); } else if (!optional) { throw TMSVishnuException(ERRCODE_BATCH_SCHEDULER_ERROR, "Missing parameter " +name); } return value; }
/** * \brief Function to cancel job: just shutdown and destroy the related VM * \param vmId the VM ID * \param jobDescr the description of the job in the form of jobId@vmId * \return raises an exception on error */ int OpenNebulaServer::cancel(const std::string& vmId) { OneRPCManager rpcManager(mcloudEndpoint); rpcManager.setMethod("one.vm.action"); rpcManager.addParam(getSessionString()); rpcManager.addParam(std::string("delete")); rpcManager.addParam(vishnu::convertToInt(vmId)); rpcManager.execute(); if (! rpcManager.lastCallSucceeded()) { throw TMSVishnuException(ERRCODE_BATCH_SCHEDULER_ERROR, rpcManager.getStringResult()); } LOG(boost::str(boost::format("[INFO] VM deleted: %1%") % vmId), LogInfo); return 0; }
/** * @brief Validate session key and return details on the user and the session * @param authKey The authentication key * @param machineId The machine Id * @param databasePtr A pointer to a database instance * @param info The resulting information */ void vishnu::validateAuthKey(const std::string& authKey, const std::string& machineId, Database* database, UserSessionInfo& info) { std::string sqlQuery = boost::str(boost::format("SELECT vsession.numsessionid, " " machine.address, machine.nummachineid," " users.numuserid, users.userid, users.privilege, " " account.aclogin, account.home" " FROM vsession, users, account, machine" " WHERE vsession.sessionkey='%1%'" " AND vsession.state=%2%" " AND users.numuserid=vsession.users_numuserid" " AND users.numuserid=account.users_numuserid" " AND account.status=%3%" " AND account.machine_nummachineid=machine.nummachineid" " AND machine.machineid='%4%';" ) % database->escapeData(authKey) % vishnu::SESSION_ACTIVE % vishnu::STATUS_ACTIVE % database->escapeData(machineId)); boost::scoped_ptr<DatabaseResult> sqlResult(database->getResult(sqlQuery)); if (sqlResult->getNbTuples() < 1) { throw TMSVishnuException(ERRCODE_PERMISSION_DENIED, "Can't get user information from the session token provided"); } std::vector<std::string> rowResult = sqlResult->get(0); std::vector<std::string>::iterator rowResultIter = rowResult.begin(); info.num_session = vishnu::convertToInt(*rowResultIter++); info.machine_address = *rowResultIter++; info.num_machine = *rowResultIter++; info.num_user = vishnu::convertToInt(*rowResultIter++); info.userid = *rowResultIter++; info.user_privilege = vishnu::convertToInt(*rowResultIter++); info.user_aclogin = *rowResultIter++; info.user_achome = *rowResultIter++; }
/** * @brief Validate session key and return details on the user and the session * @param authKey The authentication key * @param databasePtr A pointer to a database instance * @param info The resulting information */ void vishnu::validateAuthKey(const std::string& authKey, Database* database, UserSessionInfo& info) { std::string sqlQuery = boost::str( boost::format("SELECT vsession.numsessionid, " " users.numuserid, users.userid, users.privilege, " " account.aclogin, account.home" " FROM vsession, users, account" " WHERE vsession.sessionkey='%1%'" " AND vsession.state=%2%" " AND account.status=%3%" " AND vsession.users_numuserid=users.numuserid" " AND vsession.users_numuserid=account.users_numuserid" ) % database->escapeData(authKey) % vishnu::SESSION_ACTIVE % vishnu::STATUS_ACTIVE ); boost::scoped_ptr<DatabaseResult> sqlResult(database->getResult(sqlQuery)); if (sqlResult->getNbTuples() < 1) { throw TMSVishnuException(ERRCODE_INVALID_PARAM, "Can't get user local account. Check that:\n" " * your session is still active\n" " * you have a local account on this server"); } std::vector<std::string> rowResult = sqlResult->get(0); std::vector<std::string>::iterator rowResultIter = rowResult.begin(); info.num_session = vishnu::convertToInt(*rowResultIter++); info.num_user = vishnu::convertToInt(*rowResultIter++); info.userid = *rowResultIter++; info.user_privilege = vishnu::convertToInt(*rowResultIter++); info.user_aclogin = *rowResultIter++; info.user_achome = *rowResultIter++; }
/** * \brief Function to list sessions information * \return The pointer to the UMS_Data::ListSessions containing sessions information * \return raises an exception on error */ TMS_Data::ListProgression* list(TMS_Data::ProgressOptions_ptr options) { std::vector<std::string> results; std::vector<std::string>::iterator iter; std::string batchJobId; int status; long startTime; long walltime; TMS_Data::TMS_DataFactory_ptr ecoreFactory = TMS_Data::TMS_DataFactory::_instance(); mlistObject = ecoreFactory->createListProgression(); std::string sqlRequest = "SELECT jobId, jobName, wallClockLimit, endDate, status, batchJobId " " FROM vsession, job " " WHERE vsession.numsessionid=job.vsession_numsessionid "; std::string machineId = options->getMachineId(); if (!machineId.empty()){ checkMachineId(machineId); sqlRequest += " AND submitMachineId='"+mdatabaseInstance->escapeData(machineId)+"'"; } if (! options->getJobId().empty()) { std::string jobId = options->getJobId(); sqlRequest.append(" and jobId='"+mdatabaseInstance->escapeData(jobId)+"'"); boost::scoped_ptr<DatabaseResult> sqlResult(ServerXMS::getInstance()->getDatabaseVishnu()->getResult(sqlRequest.c_str())); if(sqlResult->getNbTuples() == 0) { throw TMSVishnuException(ERRCODE_UNKNOWN_JOBID); } } else { sqlRequest.append(" and owner='"+mdatabaseInstance->escapeData(options->getUser())+"'"); } sqlRequest.append(" and status < 5 order by jobId"); boost::scoped_ptr<DatabaseResult> sqlResult(ServerXMS::getInstance()->getDatabaseVishnu()->getResult(sqlRequest.c_str())); if (sqlResult->getNbTuples() != 0){ for (size_t i = 0; i < sqlResult->getNbTuples(); ++i) { results.clear(); results = sqlResult->get(i); iter = results.begin(); TMS_Data::Progression_ptr job = ecoreFactory->createProgression(); job->setJobId(*iter); job->setJobName(*(++iter)); walltime = vishnu::convertToInt(*(++iter)); job->setWallTime(walltime); job->setEndTime(vishnu::convertToLong(*(++iter))); status = vishnu::convertToInt(*(++iter)); job->setStatus(status); batchJobId = *(++iter); BatchFactory factory; BatchType batchType = ServerXMS::getInstance()->getBatchType(); std::string batchVersion = ServerXMS::getInstance()->getBatchVersion(); boost::scoped_ptr<BatchServer> batchServer(factory.getBatchServerInstance(batchType, batchVersion)); startTime = batchServer->getJobStartTime(batchJobId); if(startTime!=0) { job->setStartTime(startTime); if (status == vishnu::STATE_COMPLETED) { job->setPercent(100); } else if(status == vishnu::STATE_RUNNING) { time_t currentTime = vishnu::getCurrentTimeInUTC(); int percent = 0; time_t gap = currentTime-startTime; if (walltime == 0) { walltime = 60; } if (gap < walltime) { double ratio = 100*(double(gap)/walltime); if(ratio > 0.0 && ratio <= 1.0) { percent = 1; } else { percent = static_cast<int>(ratio); } } else { percent = 99; } job->setPercent(percent); } else { job->setPercent(0); } } else { job->setPercent(0); } mlistObject->getProgress().push_back(job); } } mlistObject->setNbJobs(mlistObject->getProgress().size()); return mlistObject; }
/** * \brief Function to solve the service solveAddWork * \param pb is a structure which corresponds to the descriptor of a profile * \return raises an exception on error */ int solveAddWork(diet_profile_t* pb) { std::string authKey; std::string workSerialized; std::string opSerialized; //IN Parameters diet_string_get(pb,0, authKey); diet_string_get(pb,1, workSerialized); diet_string_get(pb,2, opSerialized); // reset profile to handle result diet_profile_reset(pb, 2); //FIXME: SessionServer sessionServer = SessionServer(authKey); TMS_Data::AddWorkOptions_ptr workop = NULL; TMS_Data::Work_ptr work = NULL; try { std::string msgComp = ""; //MAPPER CREATION Mapper *mapper = MapperRegistry::getInstance()->getMapper(vishnu::TMSMAPPERNAME); int mapperkey = mapper->code("vishnu_add_work"); mapper->code(opSerialized, mapperkey); std::string cmd = mapper->finalize(mapperkey); //To parse the object serialized if (! vishnu::parseEmfObject(workSerialized, work)) { throw TMSVishnuException(ERRCODE_INVALID_PARAM, msgComp); } //To parse the object serialized if (! vishnu::parseEmfObject(opSerialized, workop)) { throw TMSVishnuException(ERRCODE_INVALID_PARAM, msgComp); } WorkServer workServer = WorkServer(authKey, workop->getMachineId(), work); workServer.add(workop); //To serialize the user object ::ecorecpp::serializer::serializer _ser; std::string workSerializedUpdate = _ser.serialize_str(work); // set result diet_string_set(pb,0, "success"); diet_string_set(pb,1, workSerializedUpdate); FINISH_COMMAND(authKey, cmd, vishnu::TMS, vishnu::CMDFAILED, work->getWorkId()); } catch (VishnuException& e) { try { FINISH_COMMAND(authKey, "", vishnu::TMS, vishnu::CMDFAILED, ""); } catch (VishnuException& fe) { e.appendMsgComp(fe.what()); } // set result diet_string_set(pb,0, "error"); diet_string_set(pb,1, e.what()); } delete work; return 0; }
int PosixServer::submit(const std::string& scriptPath, const TMS_Data::SubmitOptions& options, TMS_Data::ListJobs& jobSteps, char** envp){ int ret; struct trameJob resultat; struct trameSubmit op; std::string errorMsg; std::string strRet; memset(&op, 0, sizeof(op)); strncpy(op.name, options.getName().c_str(), sizeof(op.name)-1); op.walltime = options.getWallTime(); strncpy(op.outPutPath, options.getOutputPath().c_str(), sizeof(op.outPutPath)-1); strncpy(op.errorPath, options.getErrorPath().c_str(), sizeof(op.errorPath)-1); strncpy(op.workDir, options.getWorkingDir().c_str(), sizeof(op.workDir)-1); switch(fork()) { case -1: return -1; case 0: launchDaemon(); exit(0); break; default: sleep(3); // TODO : fix, sleep because need synchronisation and can't wait child that has become a daemon break; } TMS_Data::Job_ptr jobPtr = new TMS_Data::Job(); jobPtr->setStatus(vishnu::STATE_RUNNING); jobPtr->setQueue("posix"); // If no name give a default job name if (options.getName().empty()){ jobPtr->setName("posix_job"); } else { jobPtr->setName(options.getName()); } strncpy(op.jobName, jobPtr->getName().c_str(), sizeof(op.jobName)-1); ret = reqSubmit(scriptPath, &resultat, &op); if (ret == 0) { jobPtr->setOutputPath(std::string(resultat.outPutPath)); jobPtr->setBatchJobId(std::string(resultat.jobId)); jobPtr->setErrorPath(std::string(resultat.errorPath)); jobPtr->setWallClockLimit(resultat.maxTime); jobSteps.getJobs().push_back(jobPtr); } else { strRet = boost::lexical_cast<std::string>(ret); errorMsg = "Error submiting job error : " + strRet + " ernno :" + std::string(strerror(errno)); throw TMSVishnuException(ERRCODE_BATCH_SCHEDULER_ERROR, "POSIX ERROR: "+errorMsg); } return ret; }