package org.ovirt.engine.core.vdsbroker.vdsbroker;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import javax.inject.Inject;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.ovirt.engine.core.common.businessentities.VM;
import org.ovirt.engine.core.common.businessentities.VmDevice;
import org.ovirt.engine.core.common.config.Config;
import org.ovirt.engine.core.common.config.ConfigValues;
import org.ovirt.engine.core.common.vdscommands.CreateVDSCommandParameters;
import org.ovirt.engine.core.di.Injector;
import org.ovirt.engine.core.vdsbroker.builder.vminfo.LibvirtVmXmlBuilder;
import org.ovirt.engine.core.vdsbroker.builder.vminfo.VmInfoBuildUtils;
import org.ovirt.engine.core.vdsbroker.builder.vminfo.VmInfoBuilder;
import org.ovirt.engine.core.vdsbroker.builder.vminfo.VmInfoBuilderFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CreateBrokerVDSCommand<P extends CreateVDSCommandParameters> extends VmReturnVdsBrokerCommand<P> {
private static final Logger log = LoggerFactory.getLogger(CreateBrokerVDSCommand.class);
protected VM vm;
protected Map<String, Object> createInfo;
protected VmInfoBuilder builder;
@Inject
private VmInfoBuildUtils vmInfoBuildUtils;
public CreateBrokerVDSCommand(P parameters) {
super(parameters, parameters.getVm().getId());
vm = parameters.getVm();
createInfo = new HashMap<>();
builder = createBuilder();
}
@Override
protected void executeVdsBrokerCommand() {
buildVmData();
log.info("VM {}", createInfo);
if ((boolean) Config.getValue(ConfigValues.DomainXML)) {
LibvirtVmXmlBuilder builder = Injector.injectMembers(new LibvirtVmXmlBuilder(
createInfo,
vm,
getRunOncePayload()));
String libvirtXml = builder.build();
String prettyLibvirtXml = prettify(libvirtXml);
if (prettyLibvirtXml != null) {
log.info("VM {}", prettyLibvirtXml);
}
createInfo.put("xml", libvirtXml);
}
vmReturn = getBroker().create(createInfo);
proceedProxyReturnValue();
VdsBrokerObjectsBuilder.updateVMDynamicData(vm.getDynamicData(),
vmReturn.vm, getVds());
}
public static String prettify(String input) {
Source xmlInput = new StreamSource(new StringReader(input));
StringWriter stringWriter = new StringWriter();
try {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.transform(xmlInput, new StreamResult(stringWriter));
return stringWriter.toString().replace("\r\n", "\n");
} catch (Exception ex) {
log.error("Failed to produce pretty-print of {}", input);
log.error("Exception:", ex);
return null;
}
}
private VmInfoBuilder createBuilder() {
final VmInfoBuilderFactory vmInfoBuilderFactory = Injector.get(VmInfoBuilderFactory.class);
return vmInfoBuilderFactory.createVmInfoBuilder(vm, getParameters().getVdsId(), createInfo);
}
private void buildVmData() {
builder.buildVmProperties(getParameters().getHibernationVolHandle());
builder.buildVmVideoCards();
builder.buildVmGraphicsDevices();
builder.buildVmCD(getParameters().getVmPayload());
builder.buildVmFloppy(getParameters().getVmPayload());
builder.buildVmDrives();
builder.buildVmNetworkInterfaces(getParameters().getPassthroughVnicToVfMap());
builder.buildVmNetworkCluster();
builder.buildVmBootSequence();
builder.buildVmBootOptions();
builder.buildVmSoundDevices();
builder.buildVmConsoleDevice();
builder.buildVmTimeZone();
builder.buildVmUsbDevices();
builder.buildVmMemoryBalloon();
builder.buildVmWatchdog();
builder.buildVmVirtioScsi();
builder.buildVmVirtioSerial();
builder.buildVmRngDevice();
builder.buildUnmanagedDevices();
builder.buildVmSerialNumber();
builder.buildVmNumaProperties();
builder.buildVmHostDevices();
switch (getParameters().getInitializationType()) {
case Sysprep:
String sysPrepContent = SysprepHandler.getSysPrep(
getParameters().getVm(),
getParameters().getSysPrepParams());
if (!"".equals(sysPrepContent)) {
builder.buildSysprepVmPayload(sysPrepContent);
}
break;
case CloudInit:
CloudInitHandler cloudInitHandler = new CloudInitHandler(getParameters().getVm().getVmInit());
Map<String, byte[]> cloudInitContent;
try {
cloudInitContent = cloudInitHandler.getFileData();
} catch (Exception e) {
throw new RuntimeException("Failed to build cloud-init data:", e);
}
if (cloudInitContent != null && !cloudInitContent.isEmpty()) {
builder.buildCloudInitVmPayload(cloudInitContent);
}
break;
case None:
}
}
private VmDevice getRunOncePayload() {
switch (getParameters().getInitializationType()) {
case Sysprep:
String sysPrepContent = SysprepHandler.getSysPrep(
getParameters().getVm(),
getParameters().getSysPrepParams());
return (!"".equals(sysPrepContent)) ?
vmInfoBuildUtils.createSysprepPayloadDevice(sysPrepContent, getParameters().getVm())
: null;
case CloudInit:
CloudInitHandler cloudInitHandler = new CloudInitHandler(getParameters().getVm().getVmInit());
Map<String, byte[]> cloudInitContent;
try {
cloudInitContent = cloudInitHandler.getFileData();
} catch (Exception e) {
throw new RuntimeException("Failed to build cloud-init data:", e);
}
return (cloudInitContent != null && !cloudInitContent.isEmpty()) ?
vmInfoBuildUtils.createCloudInitPayloadDevice(cloudInitContent, getParameters().getVm())
: null;
case None:
default:
return null;
}
}
}