package org.ovirt.engine.core.bll.scheduling.external;
import java.util.HashMap;
import java.util.Map;
import org.ovirt.engine.core.common.AuditLogType;
import org.ovirt.engine.core.compat.Guid;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogDirector;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogable;
import org.ovirt.engine.core.dal.dbbroker.auditloghandling.AuditLogableImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ExternalSchedulerBrokerObjectBuilder {
private static final Logger log = LoggerFactory.getLogger(ExternalSchedulerBrokerObjectBuilder.class);
private static final int RESULT_OK = 0;
private static final AuditLogDirector auditLogDirector = new AuditLogDirector();
private static void auditLogPluginError(String pluginName, String errorMessage) {
AuditLogable loggable = new AuditLogableImpl();
loggable.addCustomValue("PluginName", pluginName);
loggable.addCustomValue("ErrorMessage", errorMessage);
auditLogDirector.log(loggable, AuditLogType.EXTERNAL_SCHEDULER_PLUGIN_ERROR);
}
private static void auditLogExternalSchedulerError(String errorMessage) {
AuditLogable loggable = new AuditLogableImpl();
loggable.addCustomValue("ErrorMessage", errorMessage);
auditLogDirector.log(loggable, AuditLogType.EXTERNAL_SCHEDULER_ERROR);
}
private static Object populateCommonFields(Object xmlRpcStruct, SchedulerResult result) {
/* new response format
{
"result_code": int,
"result": [list of UUIDS],
"plugin_errors": { "plugin_name": ["errormsgs"] },
"errors": ["errormsgs"]
}
*/
if (xmlRpcStruct instanceof Object[]) { //old version of ext scheduler?
log.info("Got old XMLRPC response from external scheduler");
return xmlRpcStruct;
} else if (!(xmlRpcStruct instanceof HashMap)) {
log.error("External scheduler error, malformed filter results");
return null;
}
@SuppressWarnings("unchecked")
HashMap<String, Object> castedResult = (HashMap<String, Object>) xmlRpcStruct;
// keys will be status_code, plugin_errors, errors and result
result.setResultCode((int) castedResult.get("result_code"));
Map<String, Object[]> plugin_errors = null;
Object[] errors = null;
if (result.getResultCode() != RESULT_OK) {
plugin_errors = (HashMap<String, Object[]>)castedResult.get("plugin_errors");
errors = (Object[])castedResult.get("errors");
if (plugin_errors != null) {
for (Map.Entry<String, Object[]> entry: plugin_errors.entrySet()) {
for (Object errorMsg: entry.getValue()) {
auditLogPluginError(entry.getKey(), errorMsg.toString());
result.addPluginErrors(entry.getKey(), errorMsg.toString());
}
}
}
if (errors != null) {
for (Object msg: errors) {
auditLogExternalSchedulerError((String)msg);
result.addError((String)msg);
}
}
}
/* returns just result without any headers
so it can be passed to the old parsers
*/
return castedResult.get("result");
}
public static FilteringResult getFilteringResult(Object xmlRpcStruct) {
FilteringResult result = new FilteringResult();
Object rawResult = populateCommonFields(xmlRpcStruct, result);
if (rawResult == null) {
return result;
}
// Its a list of host IDs
for (Object hostID : (Object[]) rawResult) {
result.addHost(new Guid(hostID.toString()));
}
return result;
}
public static ScoringResult getScoreResult(Object xmlRpcStruct) {
ScoringResult result = new ScoringResult();
Object rawResult = populateCommonFields(xmlRpcStruct, result);
if (rawResult == null) {
return result;
}
// Its a list of (hostID,score) pairs
for (Object hostsIDAndScore : (Object[]) rawResult) {
if (!(hostsIDAndScore instanceof Object[])
|| ((Object[]) hostsIDAndScore).length < 2
|| ((Object[]) hostsIDAndScore).length > 3) {
// some kind of error
log.error("External scheduler error, malformed score results");
return result;
}
Object[] castedHostsIDAndScore = (Object[]) hostsIDAndScore;
// External scheduler either reports cumulative data (just two fields - host, weight)
// or per policy unit data (three fields - host, weight, policy unit name)
String policyUnitId = castedHostsIDAndScore.length > 2 ? castedHostsIDAndScore[2].toString() : null;
result.addHost(policyUnitId, Guid.createGuidFromString(castedHostsIDAndScore[0].toString()),
(Integer) castedHostsIDAndScore[1]);
}
return result;
}
public static BalanceResult getBalanceResult(Object xmlRpcStruct) {
BalanceResult result = new BalanceResult();
Object[] castedRawResult = (Object[]) populateCommonFields(xmlRpcStruct, result);
if (castedRawResult == null) {
return result;
}
for (Object hostID : (Object[]) castedRawResult[1]) {
result.addHost(new Guid(hostID.toString()));
}
if (!castedRawResult[0].toString().isEmpty()) {
result.setVmToMigrate(new Guid(castedRawResult[0].toString()));
}
return result;
}
}