diff --git a/api/src/com/cloud/hypervisor/HypervisorGuru.java b/api/src/com/cloud/hypervisor/HypervisorGuru.java new file mode 100644 index 00000000000..4768ee34ca8 --- /dev/null +++ b/api/src/com/cloud/hypervisor/HypervisorGuru.java @@ -0,0 +1,28 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.cloud.hypervisor; + +import com.cloud.offering.ServiceOffering; +import com.cloud.utils.component.Adapter; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; + +public interface HypervisorGuru extends Adapter { + VirtualMachineProfile design(VirtualMachine vm, ServiceOffering offering); + boolean check(VirtualMachineProfile profile); +} diff --git a/api/src/com/cloud/vm/NicProfile.java b/api/src/com/cloud/vm/NicProfile.java index 621472723ea..98ae97da09e 100644 --- a/api/src/com/cloud/vm/NicProfile.java +++ b/api/src/com/cloud/vm/NicProfile.java @@ -29,6 +29,12 @@ public class NicProfile { URI broadcastUri; ReservationStrategy strategy; String reservationId; + boolean defaultNic; + Integer deviceId; + + public boolean isDefaultNic() { + return defaultNic; + } public String getNetmask() { return netmask; @@ -54,6 +60,10 @@ public class NicProfile { return isolationUri; } + public void setStrategy(ReservationStrategy strategy) { + this.strategy = strategy; + } + public BroadcastDomainType getType() { return broadcastType; } @@ -69,6 +79,18 @@ public class NicProfile { public void setVmId(long vmId) { this.vmId = vmId; } + + public void setDeviceId(int deviceId) { + this.deviceId = deviceId; + } + + public void setDefaultNic(boolean defaultNic) { + this.defaultNic = defaultNic; + } + + public Integer getDeviceId() { + return deviceId; + } public void setGateway(String gateway) { this.gateway = gateway; @@ -142,7 +164,7 @@ public class NicProfile { this.ip4Address = ip4Address; } - public NicProfile(Nic nic, NetworkConfiguration network) { + public NicProfile(Nic nic, NetworkConfiguration network, URI broadcastUri, URI isolationUri) { this.id = nic.getId(); this.gateway = network.getGateway(); this.mode = network.getMode(); @@ -171,6 +193,9 @@ public class NicProfile { this.netmask = netmask; this.strategy = strategy; } + + public NicProfile() { + } public ReservationStrategy getReservationStrategy() { return strategy; diff --git a/api/src/com/cloud/vm/VirtualMachineProfile.java b/api/src/com/cloud/vm/VirtualMachineProfile.java index 4da120f75cb..a675ab42451 100644 --- a/api/src/com/cloud/vm/VirtualMachineProfile.java +++ b/api/src/com/cloud/vm/VirtualMachineProfile.java @@ -25,8 +25,8 @@ import com.cloud.offering.ServiceOffering; public class VirtualMachineProfile { VirtualMachine _vm; - int _cpus; - int _speed; // in mhz + Integer _cpus; + Integer _speed; // in mhz long _ram; // in bytes HypervisorType _hypervisorType; VirtualMachine.Type _type; @@ -34,11 +34,20 @@ public class VirtualMachineProfile { Long _templateId; List _disks; List _nics; + String _os; public VirtualMachineProfile(VirtualMachine.Type type) { this._type = type; } + public String getName() { + return _vm.getInstanceName(); + } + + public String getOs() { + return _os; + } + public long getId() { return _vm.getId(); } @@ -51,11 +60,11 @@ public class VirtualMachineProfile { return _templateId; } - public int getCpus() { + public Integer getCpus() { return _cpus; } - public int getSpeed() { + public Integer getSpeed() { return _speed; } @@ -96,13 +105,14 @@ public class VirtualMachineProfile { this._templateId = templateId; } - public VirtualMachineProfile(VirtualMachine vm, ServiceOffering offering) { + public VirtualMachineProfile(VirtualMachine vm, ServiceOffering offering, String os) { this._cpus = offering.getCpu(); this._speed = offering.getSpeed(); this._ram = offering.getRamSize(); this._templateId = vm.getTemplateId(); this._type = vm.getType(); this._vm = vm; + this._os = os; } protected VirtualMachineProfile() { diff --git a/core/src/com/cloud/agent/api/Start2Command.java b/core/src/com/cloud/agent/api/Start2Command.java index 4414b888d44..c670aef8e64 100644 --- a/core/src/com/cloud/agent/api/Start2Command.java +++ b/core/src/com/cloud/agent/api/Start2Command.java @@ -12,51 +12,15 @@ public class Start2Command extends Command { return vm; } - /* - long id; - String guestIpAddress; - String gateway; - int ramSize; - String imagePath; - String guestNetworkId; - String guestMacAddress; - String vncPassword; - String externalVlan; - String externalMacAddress; - int utilization; - int cpuWeight; - int cpu; - int networkRateMbps; - int networkRateMulticastMbps; - String hostName; - String arch; - String isoPath; - boolean bootFromISO; - String guestOSDescription; - - ---->console proxy - private ConsoleProxyVO proxy; - private int proxyCmdPort; - private String vncPort; - private String urlPort; - private String mgmt_host; - private int mgmt_port; - private boolean sslEnabled; - - ----->abstract - protected String vmName; - protected String storageHosts[] = new String[2]; - protected List volumes; - protected boolean mirroredVols = false; - protected BootloaderType bootloader = BootloaderType.PyGrub; - - */ - @Override public boolean executeInSequence() { return true; } - public Start2Command() { + protected Start2Command() { + } + + public Start2Command(VirtualMachineTO vm) { + this.vm = vm; } } diff --git a/core/src/com/cloud/agent/api/to/NetworkTO.java b/core/src/com/cloud/agent/api/to/NetworkTO.java index d6e428831f3..009fc1df7b6 100644 --- a/core/src/com/cloud/agent/api/to/NetworkTO.java +++ b/core/src/com/cloud/agent/api/to/NetworkTO.java @@ -17,6 +17,8 @@ */ package com.cloud.agent.api.to; +import java.net.URI; + import com.cloud.network.Network.BroadcastDomainType; import com.cloud.network.Network.TrafficType; @@ -24,16 +26,18 @@ import com.cloud.network.Network.TrafficType; * Transfer object to transfer network settings. */ public class NetworkTO { - private String uuid; - private String ip; - private String netmask; - private String gateway; - private String mac; - private String dns1; - private String dns2; - private Long vlan; - private BroadcastDomainType broadcastType; - private TrafficType type; + protected String uuid; + protected String ip; + protected String netmask; + protected String gateway; + protected String mac; + protected String dns1; + protected String dns2; + protected Long vlan; + protected BroadcastDomainType broadcastType; + protected TrafficType type; + protected URI broadcastUri; + protected URI isolationUri; public NetworkTO() { } @@ -150,4 +154,20 @@ public class NetworkTO { public TrafficType getType() { return type; } + + public URI getBroadcastUri() { + return broadcastUri; + } + + public void setBroadcastUri(URI broadcastUri) { + this.broadcastUri = broadcastUri; + } + + public URI getIsolationUri() { + return isolationUri; + } + + public void setIsolationuri(URI isolationUri) { + this.isolationUri = isolationUri; + } } diff --git a/core/src/com/cloud/agent/api/to/NicTO.java b/core/src/com/cloud/agent/api/to/NicTO.java index 42e4f66bd94..7da291c7e4b 100644 --- a/core/src/com/cloud/agent/api/to/NicTO.java +++ b/core/src/com/cloud/agent/api/to/NicTO.java @@ -8,6 +8,8 @@ public class NicTO extends NetworkTO { Integer controlPort; Integer networkRateMbps; Integer networkRateMulticastMbps; + String bootParams; + boolean defaultNic; public NicTO() { super(); @@ -33,4 +35,25 @@ public class NicTO extends NetworkTO { public Integer getNetworkRateMulticastMbps() { return networkRateMulticastMbps; } + + public String getBootParams() { + return bootParams; + } + + public void setBootParams(String bootParams) { + this.bootParams = bootParams; + } + + public boolean isDefaultNic() { + return defaultNic; + } + + public void setDefaultNic(boolean defaultNic) { + this.defaultNic = defaultNic; + } + + @Override + public String toString() { + return new StringBuilder("[Nic:").append(type).append("-").append(ip).append("-").append(broadcastUri).append("]").toString(); + } } diff --git a/core/src/com/cloud/agent/api/to/VirtualMachineTO.java b/core/src/com/cloud/agent/api/to/VirtualMachineTO.java index b37c2fd2426..d0ab70d9225 100644 --- a/core/src/com/cloud/agent/api/to/VirtualMachineTO.java +++ b/core/src/com/cloud/agent/api/to/VirtualMachineTO.java @@ -21,6 +21,7 @@ import java.util.Map; import com.cloud.template.VirtualMachineTemplate.BootloaderType; import com.cloud.vm.VirtualMachine.Type; +import com.cloud.vm.VirtualMachineProfile; public class VirtualMachineTO { private long id; @@ -28,8 +29,7 @@ public class VirtualMachineTO { private BootloaderType bootloader; Type type; int cpus; - Integer weight; - Integer utilization; + Integer speed; long minRam; long maxRam; String hostName; @@ -42,7 +42,19 @@ public class VirtualMachineTO { VolumeTO[] disks; NicTO[] nics; - public VirtualMachineTO() { + public VirtualMachineTO(VirtualMachineProfile profile, BootloaderType bootloader) { + this.id = profile.getId(); + this.type = profile.getType(); + this.cpus = profile.getCpus(); + this.minRam = profile.getRam(); + this.maxRam = profile.getRam(); + this.speed = profile.getSpeed(); + this.os = profile.getOs(); + this.name = profile.getName(); + this.bootloader = bootloader; + } + + protected VirtualMachineTO() { } public long getId() { @@ -81,22 +93,10 @@ public class VirtualMachineTO { this.cpus = cpus; } - public Integer getWeight() { - return weight; + public Integer getSpeed() { + return speed; } - public void setWeight(Integer weight) { - this.weight = weight; - } - - public Integer getUtilization() { - return utilization; - } - - public void setUtiliziation(Integer utilization) { - this.utilization = utilization; - } - public long getMinRam() { return minRam; } @@ -133,8 +133,13 @@ public class VirtualMachineTO { public void setOs(String os) { this.os = os; } - + public String getBootArgs() { + StringBuilder buf = new StringBuilder(bootArgs != null ? bootArgs : ""); + buf.append(" "); + for (NicTO nic : nics) { + buf.append(""); + } return bootArgs; } @@ -162,12 +167,11 @@ public class VirtualMachineTO { this.disks = disks; } - public NicTO[] getNetworks() { + public NicTO[] getNics() { return nics; } public void setNics(NicTO[] nics) { this.nics = nics; } - } diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index c231b53065c..5088840ffac 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -122,8 +122,6 @@ import com.cloud.agent.api.StartupStorageCommand; import com.cloud.agent.api.StopAnswer; import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.StoragePoolInfo; -import com.cloud.agent.api.ValidateSnapshotAnswer; -import com.cloud.agent.api.ValidateSnapshotCommand; import com.cloud.agent.api.VmStatsEntry; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer; @@ -139,7 +137,6 @@ import com.cloud.agent.api.storage.CopyVolumeCommand; import com.cloud.agent.api.storage.CreateAnswer; import com.cloud.agent.api.storage.CreateCommand; import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer; - import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.DownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; @@ -235,6 +232,8 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR protected IAgentControl _agentControl; protected boolean _isRemoteAgent = false; + int _userVMCap = 0; + final int _maxWeight = 256; protected final XenServerHost _host = new XenServerHost(); @@ -670,6 +669,10 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR } protected VIF createVif(Connection conn, String vmName, VM vm, NicTO nic) throws XmlRpcException, XenAPIException { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Creating VIF for " + vmName + " on nic " + nic); + } + VIF.Record vifr = new VIF.Record(); vifr.VM = vm; vifr.device = Integer.toString(nic.getDeviceId()); @@ -677,10 +680,13 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR Pair network = getNetworkForTraffic(conn, nic.getType()); if (nic.getBroadcastType() == BroadcastDomainType.Vlan) { - vifr.network = enableVlanNetwork(conn, nic.getVlan(), network.first(), network.second()); - } else { + URI broadcastUri = nic.getBroadcastUri(); + assert broadcastUri.getScheme().equals(BroadcastDomainType.Vlan.scheme()); + long vlan = Long.parseLong(broadcastUri.getHost()); + vifr.network = enableVlanNetwork(conn, vlan, network.first(), network.second()); + } else if (nic.getBroadcastType() == BroadcastDomainType.Native || nic.getBroadcastType() == BroadcastDomainType.LinkLocal) { vifr.network = network.first(); - } + } if (nic.getNetworkRateMbps() != null) { vifr.qosAlgorithmType = "ratelimit"; @@ -725,17 +731,11 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR } } - protected VBD createVbd(Connection conn, String vmName, VM vm, VolumeTO volume, boolean patch) throws XmlRpcException, XenAPIException { + protected VBD createVbd(Connection conn, VolumeTO volume, String vmName, VM vm) throws XmlRpcException, XenAPIException { VolumeType type = volume.getType(); VDI vdi = mount(conn, vmName, volume); - if (patch) { - if (!patchSystemVm(vdi, vmName)) { - throw new CloudRuntimeException("Unable to patch system vm"); - } - } - VBD.Record vbdr = new VBD.Record(); vbdr.VM = vm; vbdr.VDI = vdi; @@ -761,7 +761,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR return vbd; } - protected Pair createVmFromTemplate(Connection conn, VirtualMachineTO vmSpec, Host host) throws XenAPIException, XmlRpcException { + protected VM createVmFromTemplate(Connection conn, VirtualMachineTO vmSpec, Host host) throws XenAPIException, XmlRpcException { String guestOsTypeName = getGuestOsType(vmSpec.getOs()); Set templates = VM.getByNameLabel(conn, guestOsTypeName); assert templates.size() == 1 : "Should only have 1 template but found " + templates.size(); @@ -785,16 +785,27 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR setMemory(conn, vm, vmSpec.getMinRam()); vm.setVCPUsAtStartup(conn, (long)vmSpec.getCpus()); vm.setVCPUsMax(conn, (long)vmSpec.getCpus()); - vm.setVCPUsNumberLive(conn, (long)vmSpec.getCpus()); Map vcpuParams = new HashMap(); - if (vmSpec.getWeight() != null) { - vcpuParams.put("weight", Integer.toString(vmSpec.getWeight())); - } - if (vmSpec.getUtilization() != null) { - vcpuParams.put("cap", Integer.toString(vmSpec.getUtilization())); + Integer speed = vmSpec.getSpeed(); + if (speed != null) { + int utilization = _userVMCap; //cpu_cap + //Configuration cpu.uservm.cap is not available in default installation. Using this parameter is not encouraged + + int cpuWeight = _maxWeight; //cpu_weight + + // weight based allocation + cpuWeight = (int)((speed*0.99) / _host.speed * _maxWeight); + if (cpuWeight > _maxWeight) { + cpuWeight = _maxWeight; + } + + vcpuParams.put("weight", Integer.toString(cpuWeight)); + vcpuParams.put("cap", Integer.toString(utilization)); + } + if (vcpuParams.size() > 0) { vm.setVCPUsParams(conn, vcpuParams); } @@ -824,7 +835,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR } } - return new Pair(vm, vmr.uuid); + return vm; } protected String handleVmStartFailure(String vmName, VM vm, String message, Throwable th) { @@ -875,6 +886,20 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR return msg; } + protected VBD createPatchVbd(Connection conn, String vmName, VM vm) throws XmlRpcException, XenAPIException { + VBD.Record cdromVBDR = new VBD.Record(); + cdromVBDR.VM = vm; + cdromVBDR.empty = true; + cdromVBDR.bootable = false; + cdromVBDR.userdevice = "3"; + cdromVBDR.mode = Types.VbdMode.RO; + cdromVBDR.type = Types.VbdType.CD; + VBD cdromVBD = VBD.create(conn, cdromVBDR); + cdromVBD.insert(conn, VDI.getByUuid(conn, _host.systemvmisouuid)); + + return cdromVBD; + } + protected Start2Answer execute(Start2Command cmd) { VirtualMachineTO vmSpec = cmd.getVirtualMachine(); String vmName = vmSpec.getName(); @@ -888,79 +913,24 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR _vms.put(vmName, State.Starting); } - Pair v = createVmFromTemplate(conn, vmSpec, host); - vm = v.first(); + vm = createVmFromTemplate(conn, vmSpec, host); for (VolumeTO disk : vmSpec.getDisks()) { - createVbd(conn, vmName, vm, disk, disk.getType() == VolumeType.ROOT && vmSpec.getType() != VirtualMachine.Type.User); + createVbd(conn, disk, vmName, vm); + } + + if (vmSpec.getType() != VirtualMachine.Type.User) { + createPatchVbd(conn, vmName, vm); } NicTO controlNic = null; - for (NicTO nic : vmSpec.getNetworks()) { - if (nic.getControlPort() != null) { + for (NicTO nic : vmSpec.getNics()) { + if (nic.getType() == TrafficType.Control) { controlNic = nic; } createVif(conn, vmName, vm, nic); } - /* - * - VBD.Record vbdr = new VBD.Record(); - Ternary mount = mounts.get(0); - vbdr.VM = vm; - vbdr.VDI = mount.second(); - vbdr.bootable = !bootFromISO; - vbdr.userdevice = "0"; - vbdr.mode = Types.VbdMode.RW; - vbdr.type = Types.VbdType.DISK; - VBD.create(conn, vbdr); - - for (int i = 1; i < mounts.size(); i++) { - mount = mounts.get(i); - // vdi.setNameLabel(conn, cmd.getVmName() + "-DATA"); - vbdr.VM = vm; - vbdr.VDI = mount.second(); - vbdr.bootable = false; - vbdr.userdevice = Long.toString(mount.third().getDeviceId()); - vbdr.mode = Types.VbdMode.RW; - vbdr.type = Types.VbdType.DISK; - vbdr.unpluggable = true; - VBD.create(conn, vbdr); - - } - - VBD.Record cdromVBDR = new VBD.Record(); - cdromVBDR.VM = vm; - cdromVBDR.empty = true; - cdromVBDR.bootable = bootFromISO; - cdromVBDR.userdevice = "3"; - cdromVBDR.mode = Types.VbdMode.RO; - cdromVBDR.type = Types.VbdType.CD; - VBD cdromVBD = VBD.create(conn, cdromVBDR); - - String isopath = cmd.getISOPath(); - if (isopath != null) { - int index = isopath.lastIndexOf("/"); - - String mountpoint = isopath.substring(0, index); - URI uri = new URI(mountpoint); - isosr = createIsoSRbyURI(uri, cmd.getVmName(), false); - - String isoname = isopath.substring(index + 1); - - VDI isovdi = getVDIbyLocationandSR(isoname, isosr); - - if (isovdi == null) { - String msg = " can not find ISO " + cmd.getISOPath(); - s_logger.warn(msg); - return new StartAnswer(cmd, msg); - } else { - cdromVBD.insert(conn, isovdi); - } - - } - */ - vm.startOn(conn, host, false, true); if (_canBridgeFirewall) { @@ -997,12 +967,15 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR state = State.Running; return new Start2Answer(cmd); } catch (XmlRpcException e) { + s_logger.warn("Exception ", e); String msg = handleVmStartFailure(vmName, vm, "", e); return new Start2Answer(cmd, msg); } catch (XenAPIException e) { + s_logger.warn("Exception ", e); String msg = handleVmStartFailure(vmName, vm, "", e); return new Start2Answer(cmd, msg); } catch (Exception e) { + s_logger.warn("Exception ", e); String msg = handleVmStartFailure(vmName, vm, "", e); return new Start2Answer(cmd, msg); } finally { @@ -3314,19 +3287,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR return new StartConsoleProxyAnswer(cmd, msg); } } - - protected boolean patchSystemVm(VDI vdi, String vmName) { - if (vmName.startsWith("r-")) { - return patchSpecialVM(vdi, vmName, "router"); - } else if (vmName.startsWith("v-")) { - return patchSpecialVM(vdi, vmName, "consoleproxy"); - } else if (vmName.startsWith("s-")) { - return patchSpecialVM(vdi, vmName, "secstorage"); - } else { - throw new CloudRuntimeException("Tried to patch unknown type of system vm"); - } - } - + protected boolean isDeviceUsed(VM vm, Long deviceId) { // Figure out the disk number to attach the VM to @@ -3367,79 +3328,6 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR throw new CloudRuntimeException("Could not find an available slot in VM with name to attach a new disk."); } - protected boolean patchSpecialVM(VDI vdi, String vmname, String vmtype) { - // patch special vm here, domr, domp - VBD vbd = null; - Connection conn = getConnection(); - try { - Host host = Host.getByUuid(conn, _host.uuid); - - Set vms = host.getResidentVMs(conn); - - for (VM vm : vms) { - VM.Record vmrec = null; - try { - vmrec = vm.getRecord(conn); - } catch (Exception e) { - String msg = "VM.getRecord failed due to " + e.toString() + " " + e.getMessage(); - s_logger.warn(msg); - continue; - } - if (vmrec.isControlDomain) { - - /* create VBD */ - VBD.Record vbdr = new VBD.Record(); - vbdr.VM = vm; - vbdr.VDI = vdi; - vbdr.bootable = false; - vbdr.userdevice = getUnusedDeviceNum(vm); - vbdr.unpluggable = true; - vbdr.mode = Types.VbdMode.RW; - vbdr.type = Types.VbdType.DISK; - - vbd = VBD.create(conn, vbdr); - - vbd.plug(conn); - - String device = vbd.getDevice(conn); - - return patchspecialvm(vmname, device, vmtype); - } - } - - } catch (XenAPIException e) { - String msg = "patchSpecialVM faile on " + _host.uuid + " due to " + e.toString(); - s_logger.warn(msg, e); - } catch (Exception e) { - String msg = "patchSpecialVM faile on " + _host.uuid + " due to " + e.getMessage(); - s_logger.warn(msg, e); - } finally { - if (vbd != null) { - try { - if (vbd.getCurrentlyAttached(conn)) { - vbd.unplug(conn); - } - vbd.destroy(conn); - } catch (XmlRpcException e) { - String msg = "Catch XmlRpcException due to " + e.getMessage(); - s_logger.warn(msg, e); - } catch (XenAPIException e) { - String msg = "Catch XenAPIException due to " + e.toString(); - s_logger.warn(msg, e); - } - - } - } - return false; - } - - protected boolean patchspecialvm(String vmname, String device, String vmtype) { - String result = callHostPlugin("vmops", "patchdomr", "vmname", vmname, "vmtype", vmtype, "device", "/dev/" + device); - if (result == null || result.isEmpty()) - return false; - return true; - } - protected String callHostPlugin(String plugin, String cmd, String... params) { //default time out is 300 s return callHostPluginWithTimeOut(plugin, cmd, 300, params); @@ -3950,6 +3838,13 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR try { Host myself = Host.getByUuid(conn, _host.uuid); + Set hcs = myself.getHostCPUs(conn); + _host.cpus = hcs.size(); + for (final HostCpu hc : hcs) { + _host.speed = hc.getSpeed(conn).intValue(); + break; + } + Set srs = SR.getByNameLabel(conn, "XenServer Tools"); if( srs.size() != 1 ) { throw new CloudRuntimeException("There are " + srs.size() + " SRs with name XenServer Tools"); @@ -4551,13 +4446,8 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR } cmd.setCaps(caps.toString()); - Set hcs = host.getHostCPUs(conn); - cpus = hcs.size(); - for (final HostCpu hc : hcs) { - speed = hc.getSpeed(conn); - } - cmd.setSpeed(speed); - cmd.setCpus(cpus); + cmd.setSpeed(_host.speed); + cmd.setCpus(_host.cpus); long free = 0; @@ -6248,10 +6138,111 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR public String storagePif1; public String storagePif2; public String pool; + public int speed; + public int cpus; } /*Override by subclass*/ protected String getGuestOsType(String stdType) { return stdType; } + +/* + protected boolean patchSystemVm(VDI vdi, String vmName, VirtualMachine.Type type) { + if (type == VirtualMachine.Type.DomainRouter) { + return patchSpecialVM(vdi, vmName, "router"); + } else if (type == VirtualMachine.Type.ConsoleProxy) { + return patchSpecialVM(vdi, vmName, "consoleproxy"); + } else if (type == VirtualMachine.Type.SecondaryStorageVm) { + return patchSpecialVM(vdi, vmName, "secstorage"); + } else { + throw new CloudRuntimeException("Tried to patch unknown type of system vm"); + } + } + + protected boolean patchSystemVm(VDI vdi, String vmName) { + if (vmName.startsWith("r-")) { + return patchSpecialVM(vdi, vmName, "router"); + } else if (vmName.startsWith("v-")) { + return patchSpecialVM(vdi, vmName, "consoleproxy"); + } else if (vmName.startsWith("s-")) { + return patchSpecialVM(vdi, vmName, "secstorage"); + } else { + throw new CloudRuntimeException("Tried to patch unknown type of system vm"); + } + } + + protected boolean patchSpecialVM(VDI vdi, String vmname, String vmtype) { + // patch special vm here, domr, domp + VBD vbd = null; + Connection conn = getConnection(); + try { + Host host = Host.getByUuid(conn, _host.uuid); + + Set vms = host.getResidentVMs(conn); + + for (VM vm : vms) { + VM.Record vmrec = null; + try { + vmrec = vm.getRecord(conn); + } catch (Exception e) { + String msg = "VM.getRecord failed due to " + e.toString() + " " + e.getMessage(); + s_logger.warn(msg); + continue; + } + if (vmrec.isControlDomain) { + + VBD.Record vbdr = new VBD.Record(); + vbdr.VM = vm; + vbdr.VDI = vdi; + vbdr.bootable = false; + vbdr.userdevice = getUnusedDeviceNum(vm); + vbdr.unpluggable = true; + vbdr.mode = Types.VbdMode.RW; + vbdr.type = Types.VbdType.DISK; + + vbd = VBD.create(conn, vbdr); + + vbd.plug(conn); + + String device = vbd.getDevice(conn); + + return patchspecialvm(vmname, device, vmtype); + } + } + + } catch (XenAPIException e) { + String msg = "patchSpecialVM faile on " + _host.uuid + " due to " + e.toString(); + s_logger.warn(msg, e); + } catch (Exception e) { + String msg = "patchSpecialVM faile on " + _host.uuid + " due to " + e.getMessage(); + s_logger.warn(msg, e); + } finally { + if (vbd != null) { + try { + if (vbd.getCurrentlyAttached(conn)) { + vbd.unplug(conn); + } + vbd.destroy(conn); + } catch (XmlRpcException e) { + String msg = "Catch XmlRpcException due to " + e.getMessage(); + s_logger.warn(msg, e); + } catch (XenAPIException e) { + String msg = "Catch XenAPIException due to " + e.toString(); + s_logger.warn(msg, e); + } + + } + } + return false; + } + + protected boolean patchspecialvm(String vmname, String device, String vmtype) { + String result = callHostPlugin("vmops", "patchdomr", "vmname", vmname, "vmtype", vmtype, "device", "/dev/" + device); + if (result == null || result.isEmpty()) + return false; + return true; + } +*/ + } diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index de3af5a624b..5558515efc9 100644 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -138,6 +138,7 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.ExecutionException; import com.cloud.utils.net.NetUtils; import com.cloud.vm.ConsoleProxyVO; +import com.cloud.vm.NicProfile; import com.cloud.vm.State; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; @@ -510,7 +511,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach @Override public ConsoleProxyVO startProxy(long proxyVmId, long startEventId) { try { - return start(proxyVmId, startEventId); + return start2(proxyVmId, startEventId); } catch (StorageUnavailableException e) { s_logger.warn("Exception while trying to start console proxy", e); return null; @@ -857,7 +858,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach if (s_logger.isDebugEnabled()) s_logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId); - Map context = createProxyInstance(dataCenterId); + Map context = createProxyInstance2(dataCenterId); long proxyVmId = (Long) context.get("proxyVmId"); if (proxyVmId == 0) { @@ -897,7 +898,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach if (s_logger.isDebugEnabled()) s_logger.debug("Assign console proxy from a newly started instance for request from data center : " + dataCenterId); - Map context = createProxyInstance(dataCenterId); + Map context = createProxyInstance2(dataCenterId); long proxyVmId = (Long) context.get("proxyVmId"); if (proxyVmId == 0) { @@ -1035,16 +1036,21 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach AccountVO systemAcct = _accountMgr.getSystemAccount(); DataCenterDeployment plan = new DataCenterDeployment(dataCenterId, 1); - - List offerings = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemVmControlNetwork, NetworkOfferingVO.SystemVmManagementNetwork, NetworkOfferingVO.SystemVmPublicNetwork); - List profiles = new ArrayList(offerings.size()); + + List defaultOffering = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemVmPublicNetwork); + List offerings = _networkMgr.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemVmControlNetwork, NetworkOfferingVO.SystemVmManagementNetwork); + List> networks = new ArrayList>(offerings.size() + 1); + NicProfile defaultNic = new NicProfile(); + defaultNic.setDefaultNic(true); + defaultNic.setDeviceId(2); + networks.add(new Pair(_networkMgr.setupNetworkConfiguration(systemAcct, defaultOffering.get(0), plan), defaultNic)); for (NetworkOfferingVO offering : offerings) { - profiles.add(_networkMgr.setupNetworkConfiguration(_accountMgr.getSystemAccount(), offering, plan)); + networks.add(new Pair(_networkMgr.setupNetworkConfiguration(systemAcct, offering, plan), null)); } ConsoleProxyVO proxy = new ConsoleProxyVO(id, _serviceOffering.getId(), name, _template.getId(), _template.getGuestOSId(), dataCenterId, systemAcct.getDomainId(), systemAcct.getId(), 0); proxy = _consoleProxyDao.persist(proxy); try { - VirtualMachineProfile vmProfile = _vmMgr.allocate(proxy, _template, _serviceOffering, profiles, plan, _accountMgr.getSystemAccount()); + VirtualMachineProfile vmProfile = _vmMgr.allocate(proxy, _template, _serviceOffering, networks, plan, systemAcct); } catch (InsufficientCapacityException e) { s_logger.warn("InsufficientCapacity", e); throw new CloudRuntimeException("Insufficient capacity exception", e); @@ -1422,7 +1428,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach try { if (proxyLock.lock(ACQUIRE_GLOBAL_LOCK_TIMEOUT_FOR_SYNC)) { try { - readyProxy = start(readyProxy.getId(), 0); + readyProxy = start2(readyProxy.getId(), 0); } finally { proxyLock.unlock(); } diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java new file mode 100644 index 00000000000..1ed056f0c6e --- /dev/null +++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.cloud.hypervisor; + +import com.cloud.utils.component.AdapterBase; + +public abstract class HypervisorGuruBase extends AdapterBase implements HypervisorGuru { + protected HypervisorGuruBase() { + super(); + } +} diff --git a/server/src/com/cloud/hypervisor/XenServerGuru.java b/server/src/com/cloud/hypervisor/XenServerGuru.java new file mode 100644 index 00000000000..4579e21b0e8 --- /dev/null +++ b/server/src/com/cloud/hypervisor/XenServerGuru.java @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.cloud.hypervisor; + +import javax.ejb.Local; + +import com.cloud.offering.ServiceOffering; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; + +@Local(value=HypervisorGuru.class) +public class XenServerGuru extends HypervisorGuruBase implements HypervisorGuru { + + protected XenServerGuru() { + super(); + } + + @Override + public VirtualMachineProfile design(VirtualMachine vm, ServiceOffering offering) { + return null; + } + + @Override + public boolean check(VirtualMachineProfile profile) { + return true; + } + +} diff --git a/server/src/com/cloud/network/NetworkConfigurationVO.java b/server/src/com/cloud/network/NetworkConfigurationVO.java index dd3ee6cc466..8a9f81520b1 100644 --- a/server/src/com/cloud/network/NetworkConfigurationVO.java +++ b/server/src/com/cloud/network/NetworkConfigurationVO.java @@ -77,6 +77,9 @@ public class NetworkConfigurationVO implements NetworkConfiguration { @Enumerated(value=EnumType.STRING) State state; + @Column(name="dns") + String dns; + public NetworkConfigurationVO() { } @@ -185,6 +188,14 @@ public class NetworkConfigurationVO implements NetworkConfiguration { return dataCenterId; } + public String getDns() { + return dns; + } + + public void setDns(String dns) { + this.dns = dns; + } + @Override public boolean equals(Object obj) { if (!(obj instanceof NetworkConfigurationVO)) { diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index c89c388d045..baaf5cde26c 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -18,6 +18,7 @@ package com.cloud.network; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -2465,36 +2466,87 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager int deviceId = 0; + boolean[] deviceIds = new boolean[networks.size()]; + Arrays.fill(deviceIds, false); + + List nics = new ArrayList(networks.size()); + NicVO defaultNic = null; + for (Pair network : networks) { - NetworkGuru concierge = _networkGurus.get(network.first().getGuruName()); - NicProfile profile = concierge.allocate(network.first(), network.second(), vm); + NetworkConfigurationVO config = network.first(); + NetworkGuru concierge = _networkGurus.get(config.getGuruName()); + NicProfile requested = network.second(); + NicProfile profile = concierge.allocate(config, requested, vm); if (profile == null) { continue; } - NicVO vo = new NicVO(concierge.getName(), vm.getId(), network.first().getId()); - vo.setDeviceId(deviceId++); + NicVO vo = new NicVO(concierge.getName(), vm.getId(), config.getId()); vo.setMode(network.first().getMode()); - if (profile.getIp4Address() != null) { - vo.setIp4Address(profile.getIp4Address()); - vo.setState(NicVO.State.Reserved); + + while (deviceIds[deviceId] && deviceId < deviceIds.length) { + deviceId++; } - if (profile.getMacAddress() != null) { - vo.setMacAddress(profile.getMacAddress()); - } + deviceId = applyProfileToNic(vo, profile, deviceId); - if (profile.getMode() != null) { - vo.setMode(profile.getMode()); - } - vo = _nicDao.persist(vo); - nicProfiles.add(new NicProfile(vo, network.first())); + + if (vo.isDefaultNic()) { + if (defaultNic != null) { + throw new IllegalArgumentException("You cannot specify two nics as default nics: nic 1 = " + defaultNic + "; nic 2 = " + vo); + } + defaultNic = vo; + } + + int devId = vo.getDeviceId(); + if (devId > deviceIds.length) { + throw new IllegalArgumentException("Device id for nic is too large: " + vo); + } + if (deviceIds[devId]) { + throw new IllegalArgumentException("Conflicting device id for two different nics: " + devId); + } + + deviceIds[devId] = true; + nics.add(vo); + nicProfiles.add(new NicProfile(vo, network.first(), vo.getBroadcastUri(), vo.getIsolationUri())); } + + if (defaultNic == null && nics.size() > 2) { + throw new IllegalArgumentException("Default Nic was not set."); + } else if (nics.size() == 1) { + nics.get(0).setDefaultNic(true); + } + txn.commit(); return nicProfiles; } + protected Integer applyProfileToNic(NicVO vo, NicProfile profile, Integer deviceId) { + if (profile.getDeviceId() != null) { + vo.setDeviceId(profile.getDeviceId()); + } else if (deviceId != null ) { + vo.setDeviceId(deviceId++); + } + + vo.setDefaultNic(profile.isDefaultNic()); + + if (profile.getIp4Address() != null) { + vo.setIp4Address(profile.getIp4Address()); + vo.setState(NicVO.State.Reserved); + } + + if (profile.getMacAddress() != null) { + vo.setMacAddress(profile.getMacAddress()); + } + + vo.setMode(profile.getMode()); + vo.setNetmask(profile.getNetmask()); + vo.setGateway(profile.getGateway()); + + return deviceId; + } + protected NicTO toNicTO(NicVO nic, NetworkConfigurationVO config) { NicTO to = new NicTO(); to.setDeviceId(nic.getDeviceId()); @@ -2503,6 +2555,17 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager to.setIp(nic.getIp4Address()); to.setNetmask(nic.getNetmask()); to.setMac(nic.getMacAddress()); + if (config.getDns() != null) { + String[] tokens = config.getDns().split(","); + to.setDns1(tokens[0]); + if (tokens.length > 2) { + to.setDns2(tokens[1]); + } + } + to.setGateway(config.getGateway()); + to.setDefaultNic(nic.isDefaultNic()); + to.setBroadcastUri(nic.getBroadcastUri()); + to.setIsolationuri(nic.getIsolationUri()); return to; } @@ -2548,7 +2611,7 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager NicProfile toNicProfile(NicVO nic) { NetworkConfiguration config = _networkProfileDao.findById(nic.getNetworkConfigurationId()); - NicProfile profile = new NicProfile(nic, config); + NicProfile profile = new NicProfile(nic, config, nic.getBroadcastUri(), nic.getIsolationUri()); return profile; } diff --git a/server/src/com/cloud/network/configuration/PodBasedNetworkGuru.java b/server/src/com/cloud/network/configuration/PodBasedNetworkGuru.java index cf72ccd8aa7..6853bafbd65 100644 --- a/server/src/com/cloud/network/configuration/PodBasedNetworkGuru.java +++ b/server/src/com/cloud/network/configuration/PodBasedNetworkGuru.java @@ -25,7 +25,6 @@ import com.cloud.resource.Resource.ReservationStrategy; import com.cloud.user.Account; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.Inject; -import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.vm.NicProfile; import com.cloud.vm.VirtualMachineProfile; @@ -61,11 +60,12 @@ public class PodBasedNetworkGuru extends AdapterBase implements NetworkGuru { } if (nic != null) { - throw new CloudRuntimeException("Does not support nic configuration"); - } + nic.setStrategy(ReservationStrategy.Start); + } else { + nic = new NicProfile(ReservationStrategy.Start, null, null, null, null); + } - NicProfile profile = new NicProfile(ReservationStrategy.Start, null, null, null, null); - return profile; + return nic; } @Override diff --git a/server/src/com/cloud/network/configuration/PublicNetworkGuru.java b/server/src/com/cloud/network/configuration/PublicNetworkGuru.java index 9e28c4c62fc..54acbfb45ce 100644 --- a/server/src/com/cloud/network/configuration/PublicNetworkGuru.java +++ b/server/src/com/cloud/network/configuration/PublicNetworkGuru.java @@ -28,7 +28,6 @@ import com.cloud.user.Account; import com.cloud.utils.Pair; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.component.Inject; -import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.NicProfile; import com.cloud.vm.VirtualMachineProfile; @@ -59,11 +58,13 @@ public class PublicNetworkGuru extends AdapterBase implements NetworkGuru { return null; } - if (nic != null) { - throw new CloudRuntimeException("Unsupported nic settings"); + if (nic == null) { + nic = new NicProfile(ReservationStrategy.Create, null, null, null, null); + } else { + nic.setStrategy(ReservationStrategy.Create); } - - return new NicProfile(ReservationStrategy.Create, null, null, null, null); + + return nic; } @Override diff --git a/server/src/com/cloud/storage/allocator/GarbageCollectingStoragePoolAllocator.java b/server/src/com/cloud/storage/allocator/GarbageCollectingStoragePoolAllocator.java index 7de9b6614e7..2d77c74c136 100644 --- a/server/src/com/cloud/storage/allocator/GarbageCollectingStoragePoolAllocator.java +++ b/server/src/com/cloud/storage/allocator/GarbageCollectingStoragePoolAllocator.java @@ -38,7 +38,7 @@ import com.cloud.vm.VMInstanceVO; @Local(value=StoragePoolAllocator.class) public class GarbageCollectingStoragePoolAllocator extends AbstractStoragePoolAllocator { - private static final Logger s_logger = Logger.getLogger(LocalStoragePoolAllocator.class); + private static final Logger s_logger = Logger.getLogger(GarbageCollectingStoragePoolAllocator.class); StoragePoolAllocator _firstFitStoragePoolAllocator; StoragePoolAllocator _localStoragePoolAllocator; diff --git a/server/src/com/cloud/vm/MauriceMoss.java b/server/src/com/cloud/vm/MauriceMoss.java index 5163afed108..d6a80dc8202 100644 --- a/server/src/com/cloud/vm/MauriceMoss.java +++ b/server/src/com/cloud/vm/MauriceMoss.java @@ -29,7 +29,11 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Start2Answer; +import com.cloud.agent.api.Start2Command; +import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VolumeTO; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.deploy.DeployDestination; @@ -38,6 +42,7 @@ import com.cloud.deploy.DeploymentPlanner; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.StorageUnavailableException; import com.cloud.network.NetworkConfigurationVO; import com.cloud.network.NetworkManager; @@ -45,10 +50,15 @@ import com.cloud.offering.ServiceOffering; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DiskOfferingVO; +import com.cloud.storage.GuestOSVO; +import com.cloud.storage.Storage; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.StorageManager; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Volume.VolumeType; +import com.cloud.storage.dao.GuestOSDao; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.template.VirtualMachineTemplate.BootloaderType; import com.cloud.user.AccountVO; import com.cloud.utils.Journal; import com.cloud.utils.NumbersUtil; @@ -72,6 +82,8 @@ public class MauriceMoss implements VmManager { @Inject private AgentManager _agentMgr; @Inject private VMInstanceDao _vmDao; @Inject private ServiceOfferingDao _offeringDao; + @Inject private GuestOSDao _guestOsDao; + @Inject private VMTemplateDao _templateDao; @Inject(adapter=DeploymentPlanner.class) private Adapters _planners; @@ -90,8 +102,15 @@ public class MauriceMoss implements VmManager { if (s_logger.isDebugEnabled()) { s_logger.debug("Allocating entries for VM: " + vm); } + + // Determine the VM's OS description + GuestOSVO guestOS = _guestOsDao.findById(vm.getGuestOSId()); + if (guestOS == null) { + throw new CloudRuntimeException("Guest OS is not set"); + } + //VMInstanceVO vm = _vmDao.findById(vm.getId()); - VirtualMachineProfile vmProfile = new VirtualMachineProfile(vm, serviceOffering); + VirtualMachineProfile vmProfile = new VirtualMachineProfile(vm, serviceOffering, guestOS.getName()); Transaction txn = Transaction.currentTxn(); txn.start(); @@ -145,13 +164,9 @@ public class MauriceMoss implements VmManager { public VirtualMachineProfile allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, - List networkProfiles, + List> networks, DeploymentPlan plan, AccountVO owner) throws InsufficientCapacityException { - List> networks = new ArrayList>(networkProfiles.size()); - for (NetworkConfigurationVO profile : networkProfiles) { - networks.add(new Pair(profile, null)); - } return allocate(vm, template, serviceOffering, new Pair(serviceOffering, null), null, networks, plan, owner); } @@ -244,7 +259,13 @@ public class MauriceMoss implements VmManager { ServiceOffering offering = _offeringDao.findById(vm.getServiceOfferingId()); - VirtualMachineProfile vmProfile = new VirtualMachineProfile(vm, offering); + // Determine the VM's OS description + GuestOSVO guestOS = _guestOsDao.findById(vm.getGuestOSId()); + if (guestOS == null) { + throw new CloudRuntimeException("Guest OS is not set"); + } + VirtualMachineProfile vmProfile = new VirtualMachineProfile(vm, offering, guestOS.getName()); + _vmDao.updateIf(vm, Event.StartRequested, null); Set avoids = new HashSet(); int retry = _retry; @@ -265,18 +286,45 @@ public class MauriceMoss implements VmManager { vm.setDataCenterId(dest.getDataCenter().getId()); vm.setPodId(dest.getPod().getId()); - _vmDao.updateIf(vm, Event.StartRequested, dest.getHost().getId()); + _vmDao.updateIf(vm, Event.OperationRetry, dest.getHost().getId()); - VirtualMachineTO vmTO = new VirtualMachineTO(); + VMTemplateVO template = _templateDao.findById(vm.getTemplateId()); + + BootloaderType bt = BootloaderType.PyGrub; + if (template.getFormat() == Storage.ImageFormat.ISO || template.isRequiresHvm()) { + bt = BootloaderType.HVM; + } + + VirtualMachineTO vmTO = new VirtualMachineTO(vmProfile, bt); + VolumeTO[] volumes = null; try { - _storageMgr.prepare(vmProfile, dest); + volumes = _storageMgr.prepare(vmProfile, dest); } catch (ConcurrentOperationException e) { throw e; } catch (StorageUnavailableException e) { s_logger.warn("Unable to contact storage.", e); continue; } - _networkMgr.prepare(vmProfile, dest); + NicTO[] nics = _networkMgr.prepare(vmProfile, dest); + + vmTO.setNics(nics); + vmTO.setDisks(volumes); + + Start2Command cmd = new Start2Command(vmTO); + try { + Start2Answer answer = (Start2Answer)_agentMgr.send(dest.getHost().getId(), cmd); + if (!answer.getResult()) { + s_logger.info("Unable to start VM on " + dest.getHost() + " due to " + answer.getDetails()); + continue; + } + _vmDao.updateIf(vm, Event.OperationSucceeded, dest.getHost().getId()); + } catch (AgentUnavailableException e) { + s_logger.debug("Unable to send the start command to host " + dest.getHost()); + continue; + } catch (OperationTimedoutException e) { + s_logger.debug("Unable to send the start command to host " + dest.getHost()); + continue; + } } if (s_logger.isDebugEnabled()) { diff --git a/server/src/com/cloud/vm/NicVO.java b/server/src/com/cloud/vm/NicVO.java index fdc9f3a730f..239bfba49f9 100644 --- a/server/src/com/cloud/vm/NicVO.java +++ b/server/src/com/cloud/vm/NicVO.java @@ -92,6 +92,9 @@ public class NicVO implements Nic { @Column(name="update_time") Date updateTime; + + @Column(name="default_nic") + boolean defaultNic; public NicVO(String reserver, long instanceId, long configurationId) { this.reserver = reserver; @@ -123,6 +126,14 @@ public class NicVO implements Nic { return state; } + public boolean isDefaultNic() { + return defaultNic; + } + + public void setDefaultNic(boolean defaultNic) { + this.defaultNic = defaultNic; + } + public String getIp6Address() { return ip6Address; } diff --git a/server/src/com/cloud/vm/VirtualMachineChecker.java b/server/src/com/cloud/vm/VirtualMachineChecker.java new file mode 100644 index 00000000000..4bac8882dcf --- /dev/null +++ b/server/src/com/cloud/vm/VirtualMachineChecker.java @@ -0,0 +1,28 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.cloud.vm; + +import java.util.List; + +import com.cloud.deploy.DeployDestination; +import com.cloud.utils.Pair; + +public interface VirtualMachineChecker { + boolean finalizeDeployment(VirtualMachineProfile vm, DeployDestination dest); + boolean finalizeDeployments(List> deployments); +} diff --git a/server/src/com/cloud/vm/VmManager.java b/server/src/com/cloud/vm/VmManager.java index 7c33a8969dd..ca97fc5b303 100644 --- a/server/src/com/cloud/vm/VmManager.java +++ b/server/src/com/cloud/vm/VmManager.java @@ -58,7 +58,7 @@ public interface VmManager extends Manager { VirtualMachineProfile allocate(T vm, VMTemplateVO template, ServiceOfferingVO serviceOffering, - List networkProfiles, + List> networkProfiles, DeploymentPlan plan, AccountVO owner) throws InsufficientCapacityException, StorageUnavailableException; diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index f4b0b23ed87..8cfe9c1571b 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -103,7 +103,8 @@ CREATE TABLE `cloud`.`network_configurations` ( `network_offering_id` bigint unsigned NOT NULL COMMENT 'network offering id that this configuration is created from', `data_center_id` bigint unsigned NOT NULL COMMENT 'data center id that this configuration is used in', `guru_name` varchar(255) NOT NULL COMMENT 'who is responsible for this type of network configuration', - `state` varchar(32) NOT NULL COMMENT 'what state is this configuration in', + `state` varchar(32) NOT NULL COMMENT 'what state is this configuration in', + `dns` varchar(255) COMMENT 'comma separated DNS list', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -137,7 +138,8 @@ CREATE TABLE `cloud`.`nics` ( `device_id` int(10) COMMENT 'device id for the network when plugged into the virtual machine', `update_time` timestamp NOT NULL COMMENT 'time the state was changed', `isolation_uri` varchar(255) COMMENT 'id for isolation', - `ip6_address` varchar(32) COMMENT 'ip6 address', + `ip6_address` varchar(32) COMMENT 'ip6 address', + `default_nic` tinyint NOT NULL COMMENT "None", PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;