diff --git a/api/src/com/cloud/deploy/DeploymentPlan.java b/api/src/com/cloud/deploy/DeploymentPlan.java index a36d7b35154..f7e3f04d464 100644 --- a/api/src/com/cloud/deploy/DeploymentPlan.java +++ b/api/src/com/cloud/deploy/DeploymentPlan.java @@ -18,10 +18,13 @@ package com.cloud.deploy; /** - * Describes how a VM should be deployed. + * Describes how a VM should be deployed. * */ public interface DeploymentPlan { + // TODO: This interface is not fully developed. It really + // should be more complicated than this and allow a + // number of parameters to be specified. public long getDataCenterId(); public int getCount(); } diff --git a/api/src/com/cloud/vm/DiskProfile.java b/api/src/com/cloud/vm/DiskProfile.java index af8f2afb42d..7cfbedb1118 100644 --- a/api/src/com/cloud/vm/DiskProfile.java +++ b/api/src/com/cloud/vm/DiskProfile.java @@ -17,8 +17,8 @@ */ package com.cloud.vm; -import com.cloud.offering.DiskOffering; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.offering.DiskOffering; import com.cloud.storage.Volume; /** @@ -56,10 +56,11 @@ public class DiskProfile { this.volumeId = volumeId; } - public DiskProfile(Volume vol, DiskOffering offering) { + public DiskProfile(Volume vol, DiskOffering offering, HypervisorType hyperType) { this(vol.getId(), vol.getVolumeType(), vol.getName(), offering.getId(), vol.getSize(), offering.getTagsArray(), offering.getUseLocalStorage(), offering.getUseLocalStorage(), vol.getSize()); this.vol = vol; this.offering = offering; + this.hyperType = hyperType; } /** diff --git a/api/src/com/cloud/vm/VirtualMachineProfile.java b/api/src/com/cloud/vm/VirtualMachineProfile.java index a675ab42451..ed4a7646b43 100644 --- a/api/src/com/cloud/vm/VirtualMachineProfile.java +++ b/api/src/com/cloud/vm/VirtualMachineProfile.java @@ -105,14 +105,15 @@ public class VirtualMachineProfile { this._templateId = templateId; } - public VirtualMachineProfile(VirtualMachine vm, ServiceOffering offering, String os) { + public VirtualMachineProfile(VirtualMachine vm, ServiceOffering offering, String os, HypervisorType hypervisorType) { this._cpus = offering.getCpu(); this._speed = offering.getSpeed(); - this._ram = offering.getRamSize(); + this._ram = offering.getRamSize() * 1024l * 1024l; this._templateId = vm.getTemplateId(); this._type = vm.getType(); this._vm = vm; this._os = os; + this._hypervisorType = hypervisorType; } protected VirtualMachineProfile() { diff --git a/core/src/com/cloud/agent/api/to/NicTO.java b/core/src/com/cloud/agent/api/to/NicTO.java index 7da291c7e4b..af1ed168e38 100644 --- a/core/src/com/cloud/agent/api/to/NicTO.java +++ b/core/src/com/cloud/agent/api/to/NicTO.java @@ -5,7 +5,6 @@ package com.cloud.agent.api.to; public class NicTO extends NetworkTO { int deviceId; - Integer controlPort; Integer networkRateMbps; Integer networkRateMulticastMbps; String bootParams; @@ -13,7 +12,6 @@ public class NicTO extends NetworkTO { public NicTO() { super(); - controlPort = null; } public void setDeviceId(int deviceId) { @@ -24,10 +22,6 @@ public class NicTO extends NetworkTO { return deviceId; } - public Integer getControlPort() { - return controlPort; - } - public Integer getNetworkRateMbps() { return networkRateMbps; } diff --git a/core/src/com/cloud/agent/api/to/VirtualMachineTO.java b/core/src/com/cloud/agent/api/to/VirtualMachineTO.java index d0ab70d9225..c6511dfbcde 100644 --- a/core/src/com/cloud/agent/api/to/VirtualMachineTO.java +++ b/core/src/com/cloud/agent/api/to/VirtualMachineTO.java @@ -38,6 +38,7 @@ public class VirtualMachineTO { String bootArgs; String[] bootupScripts; boolean rebootOnCrash; + Monitor monitor; VolumeTO[] disks; NicTO[] nics; @@ -68,6 +69,14 @@ public class VirtualMachineTO { public String getName() { return name; } + + public Monitor getMonitor() { + return monitor; + } + + public void setMonitor(Monitor monitor) { + this.monitor = monitor; + } public void setName(String name) { this.name = name; @@ -143,6 +152,10 @@ public class VirtualMachineTO { return bootArgs; } + public void setBootArgs(String bootArgs) { + this.bootArgs = bootArgs; + } + public void setBootArgs(Map bootParams) { StringBuilder buf = new StringBuilder(); for (Map.Entry entry : bootParams.entrySet()) { @@ -174,4 +187,26 @@ public class VirtualMachineTO { public void setNics(NicTO[] nics) { this.nics = nics; } + + public static interface Monitor { + + } + + public static class SshMonitor implements Monitor { + String ip; + int port; + + public String getIp() { + return ip; + } + + public int getPort() { + return port; + } + + public SshMonitor(String ip, int port) { + this.ip = ip; + this.port = port; + } + } } diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 5088840ffac..0b93e2be58a 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -145,6 +145,8 @@ import com.cloud.agent.api.storage.ShareCommand; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VirtualMachineTO.Monitor; +import com.cloud.agent.api.to.VirtualMachineTO.SshMonitor; import com.cloud.agent.api.to.VolumeTO; import com.cloud.exception.InternalErrorException; import com.cloud.host.Host.Type; @@ -654,6 +656,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR if (type == TrafficType.Guest) { return new Pair(Network.getByUuid(conn, _host.guestNetwork), _host.guestPif); } else if (type == TrafficType.Control) { + setupLinkLocalNetwork(); return new Pair(Network.getByUuid(conn, _host.linkLocalNetwork), null); } else if (type == TrafficType.Management) { return new Pair(Network.getByUuid(conn, _host.privateNetwork), _host.privatePif); @@ -923,11 +926,7 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR createPatchVbd(conn, vmName, vm); } - NicTO controlNic = null; for (NicTO nic : vmSpec.getNics()) { - if (nic.getType() == TrafficType.Control) { - controlNic = nic; - } createVif(conn, vmName, vm, nic); } @@ -947,9 +946,11 @@ public abstract class CitrixResourceBase implements StoragePoolResource, ServerR } } - if (controlNic != null) { - String privateIp = controlNic.getIp(); - int cmdPort = controlNic.getControlPort(); + Monitor monitor = vmSpec.getMonitor(); + if (monitor != null && monitor instanceof SshMonitor) { + SshMonitor sshMon = (SshMonitor)monitor; + String privateIp = sshMon.getIp(); + int cmdPort = sshMon.getPort(); if (s_logger.isDebugEnabled()) { s_logger.debug("Ping command port, " + privateIp + ":" + cmdPort); diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 9f3404fd687..9053b8de79f 100644 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -58,6 +58,9 @@ import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StopAnswer; import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer; +import com.cloud.agent.api.to.NicTO; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VirtualMachineTO.SshMonitor; import com.cloud.async.AsyncJobExecutor; import com.cloud.async.AsyncJobManager; import com.cloud.async.AsyncJobVO; @@ -73,6 +76,7 @@ import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.HostPodDao; import com.cloud.dc.dao.VlanDao; import com.cloud.deploy.DataCenterDeployment; +import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; import com.cloud.domain.DomainVO; import com.cloud.event.EventState; @@ -99,6 +103,7 @@ import com.cloud.info.RunningHostInfoAgregator.ZoneHostInfo; import com.cloud.maid.StackMaid; import com.cloud.network.IpAddrAllocator; import com.cloud.network.IpAddrAllocator.networkInfo; +import com.cloud.network.Network.TrafficType; import com.cloud.network.NetworkConfigurationVO; import com.cloud.network.NetworkManager; import com.cloud.network.dao.IPAddressDao; @@ -144,6 +149,7 @@ import com.cloud.vm.State; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.Event; +import com.cloud.vm.VirtualMachineChecker; import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.VirtualMachineName; import com.cloud.vm.VirtualMachineProfile; @@ -172,7 +178,7 @@ import com.google.gson.GsonBuilder; // because sooner or later, it will be driven into Running state // @Local(value = { ConsoleProxyManager.class }) -public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMachineManager, AgentHook { +public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMachineManager, AgentHook, VirtualMachineChecker { private static final Logger s_logger = Logger.getLogger(ConsoleProxyManagerImpl.class); private static final int DEFAULT_FIND_HOST_RETRY_COUNT = 2; @@ -512,7 +518,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; @@ -528,7 +534,7 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach public ConsoleProxyVO start2(long proxyVmId, long startEventId) throws StorageUnavailableException, InsufficientCapacityException, ConcurrentOperationException { ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId); DeploymentPlan plan = new DataCenterDeployment(proxy.getDataCenterId(), 1); - return _vmMgr.start(proxy, plan); + return _vmMgr.start(proxy, plan, this); } @Override @@ -859,7 +865,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) { @@ -899,7 +905,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) { @@ -1436,7 +1442,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(); } @@ -2334,4 +2340,60 @@ public class ConsoleProxyManagerImpl implements ConsoleProxyManager, VirtualMach protected ConsoleProxyManagerImpl() { } + + @Override + public boolean finalizeDeployment(VirtualMachineTO vm, VirtualMachineProfile profile, DeployDestination dest) { + StringBuilder buf = new StringBuilder(); + buf.append(" template=domP type=consoleproxy bootproto=dhcp"); + buf.append(" host=").append(_mgmt_host); + buf.append(" port=").append(_mgmt_port); + buf.append(" name=").append(vm.getName()); + if (_sslEnabled) { + buf.append(" premium=true"); + } + buf.append(" zone=").append(dest.getDataCenter().getId()); + buf.append(" pod=").append(dest.getPod().getId()); + buf.append(" guid=Proxy.").append(vm.getId()); + buf.append(" proxy_vm=").append(vm.getId()); + NicTO controlNic = null; + for (NicTO nic : vm.getNics()) { + int deviceId = nic.getDeviceId(); + buf.append("eth").append(deviceId).append("ip=").append(nic.getIp()); + buf.append(" eth").append(deviceId).append("mask=").append(nic.getNetmask()); + if (nic.isDefaultNic()) { + buf.append(" gateway=").append(nic.getGateway()); + buf.append(" dns1=").append(nic.getDns1()); + if (nic.getDns2() != null) { + buf.append(" dns2=").append(nic.getDns2()); + } + } +// buf.append(" bootproto=dhcp"); //FIXME: Not sure what the private ip address is suppose to be. + if (nic.getType() == TrafficType.Management) { + buf.append(" localgw=").append(dest.getPod().getGateway()); + } else if (nic.getType() == TrafficType.Control) { + controlNic = nic; + } + + } + + String bootArgs = buf.toString(); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Boot Args for " + vm + ": " + bootArgs); + } + vm.setBootArgs(bootArgs); + + if (controlNic == null) { + throw new CloudRuntimeException("Didn't start a control port"); + } + + SshMonitor monitor = new SshMonitor(controlNic.getIp(), 3922); + vm.setMonitor(monitor); + + return true; + } + + @Override + public boolean finalizeDeployments(List> deployments) { + return false; + } } diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 30205aa14f9..6e30d3f3679 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -92,7 +92,6 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceInUseException; import com.cloud.exception.StorageUnavailableException; import com.cloud.host.Host; -import com.cloud.host.Host.Type; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.DetailsDao; @@ -1169,6 +1168,7 @@ public class StorageManagerImpl implements StorageManager { return null; } + @Override public Pair getAbsoluteIsoPath(long templateId, long dataCenterId) { String isoPath = null; @@ -2414,7 +2414,7 @@ public class StorageManagerImpl implements StorageManager { if (s_logger.isDebugEnabled()) { s_logger.debug("Creating volume: " + toBeCreated); } - DiskProfile diskProfile = new DiskProfile(toBeCreated, offering); + DiskProfile diskProfile = new DiskProfile(toBeCreated, offering, vm.getHypervisorType()); Set avoids = new HashSet(); StoragePool pool = null; diff --git a/server/src/com/cloud/vm/MauriceMoss.java b/server/src/com/cloud/vm/MauriceMoss.java index d6a80dc8202..218184fd6dc 100644 --- a/server/src/com/cloud/vm/MauriceMoss.java +++ b/server/src/com/cloud/vm/MauriceMoss.java @@ -110,7 +110,7 @@ public class MauriceMoss implements VmManager { } //VMInstanceVO vm = _vmDao.findById(vm.getId()); - VirtualMachineProfile vmProfile = new VirtualMachineProfile(vm, serviceOffering, guestOS.getName()); + VirtualMachineProfile vmProfile = new VirtualMachineProfile(vm, serviceOffering, guestOS.getName(), template.getHypervisorType()); Transaction txn = Transaction.currentTxn(); txn.start(); @@ -250,7 +250,7 @@ public class MauriceMoss implements VmManager { } @Override - public T start(T vm, DeploymentPlan plan) throws InsufficientCapacityException, ConcurrentOperationException { + public T start(T vm, DeploymentPlan plan, VirtualMachineChecker checker) throws InsufficientCapacityException, ConcurrentOperationException { if (s_logger.isDebugEnabled()) { s_logger.debug("Creating actual resources for VM " + vm); } @@ -258,13 +258,19 @@ public class MauriceMoss implements VmManager { Journal journal = new Journal.LogJournal("Creating " + vm, s_logger); ServiceOffering offering = _offeringDao.findById(vm.getServiceOfferingId()); + VMTemplateVO template = _templateDao.findById(vm.getTemplateId()); + + BootloaderType bt = BootloaderType.PyGrub; + if (template.getFormat() == Storage.ImageFormat.ISO || template.isRequiresHvm()) { + bt = BootloaderType.HVM; + } // 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()); + VirtualMachineProfile vmProfile = new VirtualMachineProfile(vm, offering, guestOS.getName(), template.getHypervisorType()); _vmDao.updateIf(vm, Event.StartRequested, null); Set avoids = new HashSet(); @@ -288,12 +294,6 @@ public class MauriceMoss implements VmManager { vm.setPodId(dest.getPod().getId()); _vmDao.updateIf(vm, Event.OperationRetry, dest.getHost().getId()); - 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; @@ -310,6 +310,10 @@ public class MauriceMoss implements VmManager { vmTO.setNics(nics); vmTO.setDisks(volumes); + if (checker != null) { + checker.finalizeDeployment(vmTO, vmProfile, dest); + } + Start2Command cmd = new Start2Command(vmTO); try { Start2Answer answer = (Start2Answer)_agentMgr.send(dest.getHost().getId(), cmd); diff --git a/server/src/com/cloud/vm/VirtualMachineChecker.java b/server/src/com/cloud/vm/VirtualMachineChecker.java index 4bac8882dcf..9f8038b833b 100644 --- a/server/src/com/cloud/vm/VirtualMachineChecker.java +++ b/server/src/com/cloud/vm/VirtualMachineChecker.java @@ -19,10 +19,11 @@ package com.cloud.vm; import java.util.List; +import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.deploy.DeployDestination; import com.cloud.utils.Pair; public interface VirtualMachineChecker { - boolean finalizeDeployment(VirtualMachineProfile vm, DeployDestination dest); + boolean finalizeDeployment(VirtualMachineTO vm, VirtualMachineProfile profile, 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 ca97fc5b303..b46c9ac2a7c 100644 --- a/server/src/com/cloud/vm/VmManager.java +++ b/server/src/com/cloud/vm/VmManager.java @@ -62,7 +62,7 @@ public interface VmManager extends Manager { DeploymentPlan plan, AccountVO owner) throws InsufficientCapacityException, StorageUnavailableException; - T start(T vm, DeploymentPlan plan) throws InsufficientCapacityException, StorageUnavailableException, ConcurrentOperationException; + T start(T vm, DeploymentPlan plan, VirtualMachineChecker checker) throws InsufficientCapacityException, StorageUnavailableException, ConcurrentOperationException; T stop(T vm) throws AgentUnavailableException, ConcurrentOperationException;