protected VM createVmFromTemplate(Connection conn, VirtualMachineTO vmSpec, Host host) throws XenAPIException, XmlRpcException {
String guestOsTypeName = getGuestOsType(vmSpec.getOs(), vmSpec.getBootloader() == BootloaderType.CD);
Set<VM> templates = VM.getByNameLabel(conn, guestOsTypeName);
assert templates.size() == 1 : "Should only have 1 template but found " + templates.size();
VM template = templates.iterator().next();
VM.Record vmr = template.getRecord(conn);
vmr.affinity = host;
vmr.otherConfig.remove("disks");
vmr.otherConfig.remove("default_template");
vmr.otherConfig.remove("mac_seed");
vmr.isATemplate = false;
vmr.nameLabel = vmSpec.getName();
vmr.actionsAfterCrash = Types.OnCrashBehaviour.DESTROY;
vmr.actionsAfterShutdown = Types.OnNormalExit.DESTROY;
if (isDmcEnabled(conn, host) && vmSpec.isEnableDynamicallyScaleVm()) {
//scaling is allowed
vmr.memoryStaticMin = getStaticMin(vmSpec.getOs(), vmSpec.getBootloader() == BootloaderType.CD, vmSpec.getMinRam(), vmSpec.getMaxRam());
vmr.memoryStaticMax = getStaticMax(vmSpec.getOs(), vmSpec.getBootloader() == BootloaderType.CD, vmSpec.getMinRam(), vmSpec.getMaxRam());
vmr.memoryDynamicMin = vmSpec.getMinRam();
vmr.memoryDynamicMax = vmSpec.getMaxRam();
} else {
//scaling disallowed, set static memory target
if (vmSpec.isEnableDynamicallyScaleVm() && !isDmcEnabled(conn, host)) {
s_logger.warn("Host "+ host.getHostname(conn) +" does not support dynamic scaling, so the vm " + vmSpec.getName() + " is not dynamically scalable");
}
vmr.memoryStaticMin = vmSpec.getMinRam();
vmr.memoryStaticMax = vmSpec.getMaxRam();
vmr.memoryDynamicMin = vmSpec.getMinRam();
vmr.memoryDynamicMax = vmSpec.getMaxRam();
}
if (guestOsTypeName.toLowerCase().contains("windows")) {
vmr.VCPUsMax = (long) vmSpec.getCpus();
} else {
vmr.VCPUsMax = 32L;
}
vmr.VCPUsAtStartup = (long) vmSpec.getCpus();
vmr.consoles.clear();
VM vm = VM.create(conn, vmr);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Created VM " + vm.getUuid(conn) + " for " + vmSpec.getName());
}
Map<String, String> vcpuParams = new HashMap<String, String>();
Integer speed = vmSpec.getMinSpeed();
if (speed != null) {
int cpuWeight = _maxWeight; // cpu_weight
int utilization = 0; // max CPU cap, default is unlimited
// weight based allocation, CPU weight is calculated per VCPU
cpuWeight = (int) ((speed * 0.99) / _host.speed * _maxWeight);
if (cpuWeight > _maxWeight) {
cpuWeight = _maxWeight;
}
if (vmSpec.getLimitCpuUse()) {
// CPU cap is per VM, so need to assign cap based on the number of vcpus
utilization = (int) ((vmSpec.getMaxSpeed() * 0.99 * vmSpec.getCpus()) / _host.speed * 100);
}
vcpuParams.put("weight", Integer.toString(cpuWeight));
vcpuParams.put("cap", Integer.toString(utilization));
}
if (vcpuParams.size() > 0) {
vm.setVCPUsParams(conn, vcpuParams);
}
String bootArgs = vmSpec.getBootArgs();
if (bootArgs != null && bootArgs.length() > 0) {
String pvargs = vm.getPVArgs(conn);
pvargs = pvargs + vmSpec.getBootArgs().replaceAll(" ", "%");
if (s_logger.isDebugEnabled()) {
s_logger.debug("PV args are " + pvargs);
}
vm.setPVArgs(conn, pvargs);
}
if (!(guestOsTypeName.startsWith("Windows") || guestOsTypeName.startsWith("Citrix") || guestOsTypeName.startsWith("Other"))) {
if (vmSpec.getBootloader() == BootloaderType.CD) {
DiskTO[] disks = vmSpec.getDisks();
for (DiskTO disk : disks) {
if (disk.getType() == Volume.Type.ISO ) {
TemplateObjectTO iso = (TemplateObjectTO)disk.getData();
String osType = iso.getGuestOsType();
if (osType != null) {
String isoGuestOsName = getGuestOsType(osType, vmSpec.getBootloader() == BootloaderType.CD);
if (!isoGuestOsName.equals(guestOsTypeName)) {
vmSpec.setBootloader(BootloaderType.PyGrub);
}
}
}
}
}
if (vmSpec.getBootloader() == BootloaderType.CD) {
vm.setPVBootloader(conn, "eliloader");
if (!vm.getOtherConfig(conn).containsKey("install-repository")) {
vm.addToOtherConfig(conn, "install-repository", "cdrom");
}
} else if (vmSpec.getBootloader() == BootloaderType.PyGrub) {
vm.setPVBootloader(conn, "pygrub");
} else {
vm.destroy(conn);
throw new CloudRuntimeException("Unable to handle boot loader type: " + vmSpec.getBootloader());
}
}
try {
finalizeVmMetaData(vm, conn, vmSpec);