From 8ca6f1669e236551ea456e2c544899d838ebca02 Mon Sep 17 00:00:00 2001 From: edison Date: Thu, 11 Nov 2010 17:01:02 -0800 Subject: [PATCH] start2command fro secondarys storage vm and make it work for KVM --- .../computing/LibvirtComputingResource.java | 489 ++++++++++++++---- .../resource/computing/LibvirtVMDef.java | 166 ++++-- api/src/com/cloud/vm/DiskProfile.java | 6 +- core/src/com/cloud/storage/VolumeVO.java | 1 - .../com/cloud/vm/SecondaryStorageVmVO.java | 3 +- .../consoleproxy/ConsoleProxyManagerImpl.java | 4 +- server/src/com/cloud/hypervisor/KVMGuru.java | 37 ++ .../SecondaryStorageManagerImpl.java | 139 ++++- setup/db/create-schema.sql | 8 +- 9 files changed, 692 insertions(+), 161 deletions(-) create mode 100644 server/src/com/cloud/hypervisor/KVMGuru.java diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java index ca9725d50bf..fba8ed21f51 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtComputingResource.java @@ -121,6 +121,8 @@ import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.RebootAnswer; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.RebootRouterCommand; +import com.cloud.agent.api.Start2Answer; +import com.cloud.agent.api.Start2Command; import com.cloud.agent.api.StartAnswer; import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StartConsoleProxyAnswer; @@ -134,6 +136,8 @@ import com.cloud.agent.api.StartupRoutingCommand; import com.cloud.agent.api.StopAnswer; import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.VmStatsEntry; +import com.cloud.agent.api.check.CheckSshAnswer; +import com.cloud.agent.api.check.CheckSshCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; @@ -145,28 +149,34 @@ import com.cloud.agent.api.storage.CreatePrivateTemplateCommand; import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.DownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; +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.VolumeTO; +import com.cloud.agent.api.to.VirtualMachineTO.Monitor; +import com.cloud.agent.api.to.VirtualMachineTO.SshMonitor; import com.cloud.agent.resource.computing.KVMHABase.NfsStoragePool; import com.cloud.agent.resource.computing.KVMHABase.PoolType; import com.cloud.agent.resource.computing.LibvirtStoragePoolDef.poolType; import com.cloud.agent.resource.computing.LibvirtStorageVolumeDef.volFormat; -import com.cloud.agent.resource.computing.LibvirtVMDef.consoleDef; -import com.cloud.agent.resource.computing.LibvirtVMDef.devicesDef; -import com.cloud.agent.resource.computing.LibvirtVMDef.diskDef; -import com.cloud.agent.resource.computing.LibvirtVMDef.featuresDef; -import com.cloud.agent.resource.computing.LibvirtVMDef.graphicDef; -import com.cloud.agent.resource.computing.LibvirtVMDef.guestDef; -import com.cloud.agent.resource.computing.LibvirtVMDef.guestResourceDef; -import com.cloud.agent.resource.computing.LibvirtVMDef.inputDef; -import com.cloud.agent.resource.computing.LibvirtVMDef.interfaceDef; -import com.cloud.agent.resource.computing.LibvirtVMDef.interfaceDef.hostNicType; -import com.cloud.agent.resource.computing.LibvirtVMDef.serialDef; -import com.cloud.agent.resource.computing.LibvirtVMDef.termPolicy; +import com.cloud.agent.resource.computing.LibvirtVMDef.ConsoleDef; +import com.cloud.agent.resource.computing.LibvirtVMDef.DevicesDef; +import com.cloud.agent.resource.computing.LibvirtVMDef.DiskDef; +import com.cloud.agent.resource.computing.LibvirtVMDef.FeaturesDef; +import com.cloud.agent.resource.computing.LibvirtVMDef.GraphicDef; +import com.cloud.agent.resource.computing.LibvirtVMDef.GuestDef; +import com.cloud.agent.resource.computing.LibvirtVMDef.GuestResourceDef; +import com.cloud.agent.resource.computing.LibvirtVMDef.InputDef; +import com.cloud.agent.resource.computing.LibvirtVMDef.InterfaceDef; +import com.cloud.agent.resource.computing.LibvirtVMDef.InterfaceDef.hostNicType; +import com.cloud.agent.resource.computing.LibvirtVMDef.SerialDef; +import com.cloud.agent.resource.computing.LibvirtVMDef.TermPolicy; import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource; import com.cloud.exception.InternalErrorException; import com.cloud.host.Host.Type; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.network.Network.BroadcastDomainType; +import com.cloud.network.Network.TrafficType; import com.cloud.network.NetworkEnums.RouterPrivateIpStrategy; import com.cloud.resource.ServerResource; import com.cloud.resource.ServerResourceBase; @@ -196,6 +206,7 @@ import com.cloud.vm.DiskProfile; import com.cloud.vm.DomainRouter; import com.cloud.vm.SecondaryStorageVmVO; import com.cloud.vm.State; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineName; @@ -871,14 +882,14 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv protected synchronized String startDomainRouter(StartRouterCommand cmd) { DomainRouter router = cmd.getRouter(); - List nics = null; + List nics = null; try { nics = createRouterVMNetworks(cmd); - List disks = createSystemVMDisk(cmd.getVolumes()); + List disks = createSystemVMDisk(cmd.getVolumes()); String dataDiskPath = null; - for (diskDef disk : disks) { + for (DiskDef disk : disks) { if (disk.getDiskLabel().equalsIgnoreCase("vdb")) { dataDiskPath = disk.getDiskPath(); } @@ -894,7 +905,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv startDomain(vmName, domXML); - for (interfaceDef nic : nics) { + for (InterfaceDef nic : nics) { if (nic.getHostNetType() == hostNicType.VNET) { disableBridgeForwardding(nic.getBrName()); } @@ -920,14 +931,14 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv protected synchronized String startConsoleProxy(StartConsoleProxyCommand cmd) { ConsoleProxyVO console = cmd.getProxy(); - List nics = null; + List nics = null; try { nics = createSysVMNetworks(console.getGuestMacAddress(), console.getPrivateMacAddress(), console.getPublicMacAddress(), console.getVlanId()); - List disks = createSystemVMDisk(cmd.getVolumes()); + List disks = createSystemVMDisk(cmd.getVolumes()); String dataDiskPath = null; - for (diskDef disk : disks) { + for (DiskDef disk : disks) { if (disk.getDiskLabel().equalsIgnoreCase("vdb")) { dataDiskPath = disk.getDiskPath(); } @@ -959,14 +970,14 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv protected String startSecStorageVM(StartSecStorageVmCommand cmd) { SecondaryStorageVmVO secVm = cmd.getSecondaryStorageVmVO(); - List nics = null; + List nics = null; try { nics = createSysVMNetworks(secVm.getGuestMacAddress(), secVm.getPrivateMacAddress(), secVm.getPublicMacAddress(), secVm.getVlanId()); - List disks = createSystemVMDisk(cmd.getVolumes()); + List disks = createSystemVMDisk(cmd.getVolumes()); String dataDiskPath = null; - for (diskDef disk : disks) { + for (DiskDef disk : disks) { if (disk.getDiskLabel().equalsIgnoreCase("vdb")) { dataDiskPath = disk.getDiskPath(); } @@ -995,61 +1006,61 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return null; } - private String defineVMXML(String vmName, String uuid, int memSize, int cpus, String arch, List nics, List disks, String vncPaswd, String guestOSType) { + private String defineVMXML(String vmName, String uuid, int memSize, int cpus, String arch, List nics, List disks, String vncPaswd, String guestOSType) { LibvirtVMDef vm = new LibvirtVMDef(); vm.setHvsType(_hypervisorType); vm.setDomainName(vmName); vm.setDomUUID(uuid); vm.setDomDescription(KVMGuestOsMapper.getGuestOsName(guestOSType)); - guestDef guest = new guestDef(); - guest.setGuestType(guestDef.guestType.KVM); + GuestDef guest = new GuestDef(); + guest.setGuestType(GuestDef.guestType.KVM); guest.setGuestArch(arch); guest.setMachineType("pc"); - guest.setBootOrder(guestDef.bootOrder.CDROM); - guest.setBootOrder(guestDef.bootOrder.HARDISK); + guest.setBootOrder(GuestDef.bootOrder.CDROM); + guest.setBootOrder(GuestDef.bootOrder.HARDISK); vm.addComp(guest); - guestResourceDef grd = new guestResourceDef(); + GuestResourceDef grd = new GuestResourceDef(); grd.setMemorySize(memSize*1024); grd.setVcpuNum(cpus); vm.addComp(grd); - featuresDef features = new featuresDef(); + FeaturesDef features = new FeaturesDef(); features.addFeatures("pae"); features.addFeatures("apic"); features.addFeatures("acpi"); vm.addComp(features); - termPolicy term = new termPolicy(); + TermPolicy term = new TermPolicy(); term.setCrashPolicy("destroy"); term.setPowerOffPolicy("destroy"); term.setRebootPolicy("restart"); vm.addComp(term); - devicesDef devices = new devicesDef(); + DevicesDef devices = new DevicesDef(); devices.setEmulatorPath(_hypervisorPath); - for (interfaceDef nic : nics) { + for (InterfaceDef nic : nics) { devices.addDevice(nic); } - for (diskDef disk : disks) { + for (DiskDef disk : disks) { if (!disk.isAttachDeferred()) devices.addDevice(disk); } - serialDef serial = new serialDef("pty", null, (short)0); + SerialDef serial = new SerialDef("pty", null, (short)0); devices.addDevice(serial); - consoleDef console = new consoleDef("pty", null, null, (short)0); + ConsoleDef console = new ConsoleDef("pty", null, null, (short)0); devices.addDevice(console); - graphicDef grap = new graphicDef("vnc", (short)0, true, null, null, null); + GraphicDef grap = new GraphicDef("vnc", (short)0, true, null, null, null); devices.addDevice(grap); - inputDef input = new inputDef("tablet", "usb"); + InputDef input = new InputDef("tablet", "usb"); devices.addDevice(input); vm.addComp(devices); @@ -1234,8 +1245,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return execute((DeleteStoragePoolCommand) cmd); } else if (cmd instanceof FenceCommand ) { return execute((FenceCommand) cmd); + } else if (cmd instanceof Start2Command ) { + return execute((Start2Command) cmd); } else if (cmd instanceof RoutingCommand) { return _virtRouterResource.executeRequest(cmd); + } else if (cmd instanceof CheckSshCommand) { + return execute((CheckSshCommand) cmd); } else { s_logger.warn("Unsupported command "); return Answer.createUnsupportedCommandAnswer(cmd); @@ -2553,14 +2568,14 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } protected synchronized String startVM(StartCommand cmd) { - List nics = null; + List nics = null; try { String uuid = UUID.nameUUIDFromBytes(cmd.getVmName().getBytes()).toString(); nics = createUserVMNetworks(cmd); - List disks = createVMDisk(cmd.getVolumes(), cmd.getGuestOSDescription(), cmd.getISOPath()); + List disks = createVMDisk(cmd.getVolumes(), cmd.getGuestOSDescription(), cmd.getISOPath()); @@ -2574,7 +2589,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv startDomain(cmd.getVmName(), vmDomainXML); // Attach each data volume to the VM, if there is a deferred attached disk - for (diskDef disk : disks) { + for (DiskDef disk : disks) { if (disk.isAttachDeferred()) { attachOrDetachDisk(true, cmd.getVmName(), disk.getDiskPath()); } @@ -2602,6 +2617,282 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } } + + private void handleVmStartFailure(String vmName, LibvirtVMDef vm) { + if (vm != null && vm.getDevices() != null) + cleanupVMNetworks(vm.getDevices().getInterfaces()); + } + + private LibvirtVMDef createVMFromSpec(VirtualMachineTO vmTO) { + LibvirtVMDef vm = new LibvirtVMDef(); + vm.setHvsType(_hypervisorType); + vm.setDomainName(vmTO.getName()); + vm.setDomUUID(UUID.nameUUIDFromBytes(vmTO.getName().getBytes()).toString()); + vm.setDomDescription(KVMGuestOsMapper.getGuestOsName(vmTO.getOs())); + + GuestDef guest = new GuestDef(); + guest.setGuestType(GuestDef.guestType.KVM); + guest.setGuestArch(vmTO.getArch()); + guest.setMachineType("pc"); + guest.setBootOrder(GuestDef.bootOrder.CDROM); + guest.setBootOrder(GuestDef.bootOrder.HARDISK); + + vm.addComp(guest); + + GuestResourceDef grd = new GuestResourceDef(); + grd.setMemorySize(vmTO.getMinRam()/1024); + grd.setVcpuNum(vmTO.getCpus()); + vm.addComp(grd); + + FeaturesDef features = new FeaturesDef(); + features.addFeatures("pae"); + features.addFeatures("apic"); + features.addFeatures("acpi"); + vm.addComp(features); + + TermPolicy term = new TermPolicy(); + term.setCrashPolicy("destroy"); + term.setPowerOffPolicy("destroy"); + term.setRebootPolicy("restart"); + vm.addComp(term); + + DevicesDef devices = new DevicesDef(); + devices.setEmulatorPath(_hypervisorPath); + + + SerialDef serial = new SerialDef("pty", null, (short)0); + devices.addDevice(serial); + + ConsoleDef console = new ConsoleDef("pty", null, null, (short)0); + devices.addDevice(console); + + GraphicDef grap = new GraphicDef("vnc", (short)0, true, null, null, null); + devices.addDevice(grap); + + InputDef input = new InputDef("tablet", "usb"); + devices.addDevice(input); + + vm.addComp(devices); + + return vm; + } + + private void createVifs(VirtualMachineTO vmSpec, LibvirtVMDef vm) throws InternalErrorException { + NicTO[] nics = vmSpec.getNics(); + for (int i = 0; i < nics.length; i++) { + for (NicTO nic : vmSpec.getNics()) { + if (nic.getDeviceId() == i) + createVif(vm, nic); + } + } + } + + + protected Start2Answer execute(Start2Command cmd) { + VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + String vmName = vmSpec.getName(); + LibvirtVMDef vm = null; + + State state = State.Stopped; + + try { + + synchronized (_vms) { + _vms.put(vmName, State.Starting); + } + + vm = createVMFromSpec(vmSpec); + + createVbd(vmSpec, vmName, vm); + + createVifs(vmSpec, vm); + + s_logger.debug("starting " + vmName + ": " + vm.toString()); + startDomain(vmName, vm.toString()); + + 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); + } + + String result = _virtRouterResource.connect(privateIp, cmdPort); + if (result != null) { + throw new CloudRuntimeException("Can not ping System vm " + vmName + "due to:" + result); + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("Ping command port succeeded for vm " + vmName); + } + } + + // Attach each data volume to the VM, if there is a deferred attached disk + for (DiskDef disk : vm.getDevices().getDisks()) { + if (disk.isAttachDeferred()) { + attachOrDetachDisk(true, vmName, disk.getDiskPath()); + } + } + state = State.Running; + return new Start2Answer(cmd); + } catch (Exception e) { + s_logger.warn("Exception ", e); + handleVmStartFailure(vmName, vm); + return new Start2Answer(cmd, e.getMessage()); + } finally { + synchronized (_vms) { + if (state != State.Stopped) { + _vms.put(vmName, state); + } else { + _vms.remove(vmName); + } + } + } + } + + private String getVolumePath(VolumeTO volume) throws LibvirtException, URISyntaxException { + if (volume.getType() == Volume.VolumeType.ISO) { + StorageVol vol = getVolume(_conn, volume.getPath()); + return vol.getPath(); + } else { + return volume.getPath(); + } + } + + private void createVbd(VirtualMachineTO vmSpec, String vmName, LibvirtVMDef vm) throws InternalErrorException, LibvirtException, URISyntaxException{ + boolean foundISO = false; + for (VolumeTO volume : vmSpec.getDisks()) { + String volPath = getVolumePath(volume); + + DiskDef.diskBus diskBusType = getGuestDiskModel(vmSpec.getOs()); + DiskDef disk = new DiskDef(); + if (volume.getType() == VolumeType.ISO) { + foundISO = true; + disk.defISODisk(volPath); + } else { + int devId = 0; + if (volume.getType() == VolumeType.ROOT) { + devId = 0; + } else { + devId = 1; + } + disk.defFileBasedDisk(volume.getPath(), devId, diskBusType, DiskDef.diskFmtType.QCOW2); + } + + //Centos doesn't support scsi hotplug. For other host OSes, we attach the disk after the vm is running, so that we can hotplug it. + if (volume.getType() == VolumeType.DATADISK && diskBusType != DiskDef.diskBus.VIRTIO) { + disk.setAttachDeferred(true); + } + + if (!disk.isAttachDeferred()) { + vm.getDevices().addDevice(disk); + } + } + + if (vmSpec.getType() == VirtualMachine.Type.User) { + if (!foundISO) { + /*Add iso as placeholder*/ + DiskDef iso = new DiskDef(); + iso.defISODisk(null); + vm.getDevices().addDevice(iso); + } + } else { + DiskDef iso = new DiskDef(); + iso.defISODisk(_sysvmISOPath); + vm.getDevices().addDevice(iso); + + createPatchVbd(vmName, vm, vmSpec); + } + } + + private void createPatchVbd(String vmName, LibvirtVMDef vm, VirtualMachineTO vmSpec) throws LibvirtException, InternalErrorException { + + List disks = vm.getDevices().getDisks(); + DiskDef rootDisk = disks.get(0); + + StorageVol tmplVol = createTmplDataDisk(rootDisk.getDiskPath(), 10L * 1024 * 1024); + String datadiskPath = tmplVol.getKey(); + + /*add patch disk*/ + DiskDef patchDisk = new DiskDef(); + patchDisk.defFileBasedDisk(rootDisk.getDiskPath(), 1, rootDisk.getBusType(), DiskDef.diskFmtType.RAW); + disks.add(patchDisk); + patchDisk.setDiskPath(datadiskPath); + + String bootArgs = vmSpec.getBootArgs(); + + patchSystemVm(bootArgs, datadiskPath, vmName); + + } + + private String createVlanBr(String vlanId, String nic) throws InternalErrorException{ + String brName = setVnetBrName(vlanId); + createVnet(vlanId, nic); + return brName; + } + + private InterfaceDef createVif(LibvirtVMDef vm, NicTO nic) throws InternalErrorException { + InterfaceDef intf = new InterfaceDef(); + + String vlanId = null; + if (nic.getBroadcastType() == BroadcastDomainType.Vlan) { + URI broadcastUri = nic.getBroadcastUri(); + vlanId = broadcastUri.getHost(); + s_logger.debug("vlanId: " + vlanId); + } + + if (nic.getType() == TrafficType.Guest) { + if (nic.getBroadcastType() == BroadcastDomainType.Vlan && !vlanId.equalsIgnoreCase("untagged")){ + String brName = createVlanBr(vlanId, _pifs.first()); + intf.defBridgeNet(brName, null, nic.getMac(), InterfaceDef.nicModel.VIRTIO); + } else { + intf.defBridgeNet(_privBridgeName, null, nic.getMac(), InterfaceDef.nicModel.VIRTIO); + } + } else if (nic.getType() == TrafficType.Control) { + intf.defPrivateNet(_privNwName, null, nic.getMac(), InterfaceDef.nicModel.VIRTIO); + } else if (nic.getType() == TrafficType.Public) { + if (nic.getBroadcastType() == BroadcastDomainType.Vlan && !vlanId.equalsIgnoreCase("untagged")) { + String brName = createVlanBr(vlanId, _pifs.second()); + intf.defBridgeNet(brName, null, nic.getMac(), InterfaceDef.nicModel.VIRTIO); + } else { + intf.defBridgeNet(_publicBridgeName, null, nic.getMac(), InterfaceDef.nicModel.VIRTIO); + } + } else if (nic.getType() == TrafficType.Management) { + intf.defBridgeNet(_privBridgeName, null, nic.getMac(), InterfaceDef.nicModel.VIRTIO); + } + + vm.getDevices().addDevice(intf); + return intf; + } + + + protected CheckSshAnswer execute(CheckSshCommand cmd) { + String vmName = cmd.getName(); + String privateIp = cmd.getIp(); + int cmdPort = cmd.getPort(); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Ping command port, " + privateIp + ":" + cmdPort); + } + + try { + String result = _virtRouterResource.connect(privateIp, cmdPort); + if (result != null) { + return new CheckSshAnswer(cmd, "Can not ping System vm " + vmName + "due to:" + result); + } + } catch (Exception e) { + return new CheckSshAnswer(cmd, e); + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Ping command port succeeded for vm " + vmName); + } + + return new CheckSshAnswer(cmd); + } + protected synchronized String attachOrDetachISO(String vmName, String isoPath, boolean isAttach) throws LibvirtException, URISyntaxException { String isoXml = null; if (isoPath != null && isAttach) { @@ -2609,14 +2900,14 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv isoPath = isoVol.getPath(); - diskDef iso = new diskDef(); - iso.defFileBasedDisk(isoPath, "hdc", diskDef.diskBus.IDE, diskDef.diskFmtType.RAW); - iso.setDeviceType(diskDef.deviceType.CDROM); + DiskDef iso = new DiskDef(); + iso.defFileBasedDisk(isoPath, "hdc", DiskDef.diskBus.IDE, DiskDef.diskFmtType.RAW); + iso.setDeviceType(DiskDef.deviceType.CDROM); isoXml = iso.toString(); } else { - diskDef iso = new diskDef(); - iso.defFileBasedDisk(null, "hdc", diskDef.diskBus.IDE, diskDef.diskFmtType.RAW); - iso.setDeviceType(diskDef.deviceType.CDROM); + DiskDef iso = new DiskDef(); + iso.defFileBasedDisk(null, "hdc", DiskDef.diskBus.IDE, DiskDef.diskFmtType.RAW); + iso.setDeviceType(DiskDef.deviceType.CDROM); isoXml = iso.toString(); } @@ -2664,12 +2955,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv s_logger.warn("Can't get disk dev"); return "Can't get disk dev"; } - diskDef disk = new diskDef(); + DiskDef disk = new DiskDef(); String guestOSType = getGuestType(vmName); if (isGuestPVEnabled(guestOSType)) { - disk.defFileBasedDisk(sourceFile, diskDev, diskDef.diskBus.VIRTIO, diskDef.diskFmtType.QCOW2); + disk.defFileBasedDisk(sourceFile, diskDev, DiskDef.diskBus.VIRTIO, DiskDef.diskFmtType.QCOW2); } else { - disk.defFileBasedDisk(sourceFile, diskDev, diskDef.diskBus.SCSI, diskDef.diskFmtType.QCOW2); + disk.defFileBasedDisk(sourceFile, diskDev, DiskDef.diskBus.SCSI, DiskDef.diskFmtType.QCOW2); } String xml = disk.toString(); return attachOrDetachDevice(attach, vmName, xml); @@ -3320,19 +3611,19 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return dataVol; } - private interfaceDef.nicModel getGuestNicModel(String guestOSType) { + private InterfaceDef.nicModel getGuestNicModel(String guestOSType) { if (isGuestPVEnabled(guestOSType) && !isCentosHost()) { - return interfaceDef.nicModel.VIRTIO; + return InterfaceDef.nicModel.VIRTIO; } else { - return interfaceDef.nicModel.E1000; + return InterfaceDef.nicModel.E1000; } } - private diskDef.diskBus getGuestDiskModel(String guestOSType) { + private DiskDef.diskBus getGuestDiskModel(String guestOSType) { if (isGuestPVEnabled(guestOSType) && !isCentosHost()) { - return diskDef.diskBus.VIRTIO; + return DiskDef.diskBus.VIRTIO; } else { - return diskDef.diskBus.IDE; + return DiskDef.diskBus.IDE; } } @@ -3342,12 +3633,12 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv private String getVnetIdFromBrName(String vnetBrName) { return vnetBrName.replaceAll("cloudVirBr", ""); } - private List createUserVMNetworks(StartCommand cmd) throws InternalErrorException { - List nics = new ArrayList(); - interfaceDef.nicModel nicModel = getGuestNicModel(cmd.getGuestOSDescription()); + private List createUserVMNetworks(StartCommand cmd) throws InternalErrorException { + List nics = new ArrayList(); + InterfaceDef.nicModel nicModel = getGuestNicModel(cmd.getGuestOSDescription()); String guestMac = cmd.getGuestMacAddress(); String brName; - interfaceDef pubNic = new interfaceDef(); + InterfaceDef pubNic = new InterfaceDef(); if (cmd.getGuestIpAddress() == null) { /*guest network is direct attached without external DHCP server*/ brName = _privBridgeName; @@ -3368,89 +3659,89 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv return nics; } - private List createRouterVMNetworks(StartRouterCommand cmd) throws InternalErrorException { - List nics = new ArrayList(); + private List createRouterVMNetworks(StartRouterCommand cmd) throws InternalErrorException { + List nics = new ArrayList(); DomainRouter router = cmd.getRouter(); String guestMac = router.getGuestMacAddress(); String privateMac = router.getPrivateMacAddress(); String pubMac = router.getPublicMacAddress(); String brName; - interfaceDef pubNic = new interfaceDef(); - interfaceDef privNic = new interfaceDef(); - interfaceDef vnetNic = new interfaceDef(); + InterfaceDef pubNic = new InterfaceDef(); + InterfaceDef privNic = new InterfaceDef(); + InterfaceDef vnetNic = new InterfaceDef(); /*nic 0, guest network*/ if ("untagged".equalsIgnoreCase(router.getVnet())){ - vnetNic.defBridgeNet(_privBridgeName, null, guestMac, interfaceDef.nicModel.VIRTIO); + vnetNic.defBridgeNet(_privBridgeName, null, guestMac, InterfaceDef.nicModel.VIRTIO); } else { String vnetId = getVnetId(router.getVnet()); brName = setVnetBrName(vnetId); String vnetDev = "vtap" + vnetId; createVnet(vnetId, _pifs.first()); - vnetNic.defBridgeNet(brName, null, guestMac, interfaceDef.nicModel.VIRTIO); + vnetNic.defBridgeNet(brName, null, guestMac, InterfaceDef.nicModel.VIRTIO); } nics.add(vnetNic); /*nic 1: link local*/ - privNic.defPrivateNet(_privNwName, null, privateMac, interfaceDef.nicModel.VIRTIO); + privNic.defPrivateNet(_privNwName, null, privateMac, InterfaceDef.nicModel.VIRTIO); nics.add(privNic); /*nic 2: public */ if ("untagged".equalsIgnoreCase(router.getVlanId())) { - pubNic.defBridgeNet(_publicBridgeName, null, pubMac, interfaceDef.nicModel.VIRTIO); + pubNic.defBridgeNet(_publicBridgeName, null, pubMac, InterfaceDef.nicModel.VIRTIO); } else { String vnetId = getVnetId(router.getVlanId()); brName = setVnetBrName(vnetId); String vnetDev = "vtap" + vnetId; createVnet(vnetId, _pifs.second()); - pubNic.defBridgeNet(brName, null, pubMac, interfaceDef.nicModel.VIRTIO); + pubNic.defBridgeNet(brName, null, pubMac, InterfaceDef.nicModel.VIRTIO); } nics.add(pubNic); return nics; } - private List createSysVMNetworks(String guestMac, String privMac, String pubMac, String vlanId) throws InternalErrorException { - List nics = new ArrayList(); + private List createSysVMNetworks(String guestMac, String privMac, String pubMac, String vlanId) throws InternalErrorException { + List nics = new ArrayList(); String brName; - interfaceDef pubNic = new interfaceDef(); - interfaceDef privNic = new interfaceDef(); - interfaceDef vnetNic = new interfaceDef(); + InterfaceDef pubNic = new InterfaceDef(); + InterfaceDef privNic = new InterfaceDef(); + InterfaceDef vnetNic = new InterfaceDef(); /*nic 0: link local*/ - privNic.defPrivateNet(_privNwName, null, guestMac, interfaceDef.nicModel.VIRTIO); + privNic.defPrivateNet(_privNwName, null, guestMac, InterfaceDef.nicModel.VIRTIO); nics.add(privNic); /*nic 1, priv network*/ - vnetNic.defBridgeNet(_privBridgeName, null, privMac, interfaceDef.nicModel.VIRTIO); + vnetNic.defBridgeNet(_privBridgeName, null, privMac, InterfaceDef.nicModel.VIRTIO); nics.add(vnetNic); /*nic 2: public */ if ("untagged".equalsIgnoreCase(vlanId)) { - pubNic.defBridgeNet(_publicBridgeName, null, pubMac, interfaceDef.nicModel.VIRTIO); + pubNic.defBridgeNet(_publicBridgeName, null, pubMac, InterfaceDef.nicModel.VIRTIO); } else { String vnetId = getVnetId(vlanId); brName = setVnetBrName(vnetId); String vnetDev = "vtap" + vnetId; createVnet(vnetId, _pifs.second()); - pubNic.defBridgeNet(brName, null, pubMac, interfaceDef.nicModel.VIRTIO); + pubNic.defBridgeNet(brName, null, pubMac, InterfaceDef.nicModel.VIRTIO); } nics.add(pubNic); return nics; } - private void cleanupVMNetworks(List nics) { - for (interfaceDef nic : nics) { + private void cleanupVMNetworks(List nics) { + for (InterfaceDef nic : nics) { if (nic.getHostNetType() == hostNicType.VNET) { cleanupVnet(getVnetIdFromBrName(nic.getBrName())); } } } - private List createSystemVMDisk(List vols) throws InternalErrorException, LibvirtException{ - List disks = new ArrayList(); + private List createSystemVMDisk(List vols) throws InternalErrorException, LibvirtException{ + List disks = new ArrayList(); // Get the root volume List rootVolumes = findVolumes(vols, VolumeType.ROOT, true); @@ -3464,24 +3755,24 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv StorageVol tmplVol = createTmplDataDisk(rootkPath, 10L * 1024 * 1024); String datadiskPath = tmplVol.getKey(); - diskDef hda = new diskDef(); - hda.defFileBasedDisk(rootkPath, "vda", diskDef.diskBus.VIRTIO, diskDef.diskFmtType.QCOW2); + DiskDef hda = new DiskDef(); + hda.defFileBasedDisk(rootkPath, "vda", DiskDef.diskBus.VIRTIO, DiskDef.diskFmtType.QCOW2); disks.add(hda); - diskDef hdb = new diskDef(); - hdb.defFileBasedDisk(datadiskPath, "vdb", diskDef.diskBus.VIRTIO, diskDef.diskFmtType.RAW); + DiskDef hdb = new DiskDef(); + hdb.defFileBasedDisk(datadiskPath, "vdb", DiskDef.diskBus.VIRTIO, DiskDef.diskFmtType.RAW); disks.add(hdb); - diskDef hdc = new diskDef(); - hdc.defFileBasedDisk(_sysvmISOPath, "hdc", diskDef.diskBus.IDE, diskDef.diskFmtType.RAW); - hdc.setDeviceType(diskDef.deviceType.CDROM); + DiskDef hdc = new DiskDef(); + hdc.defFileBasedDisk(_sysvmISOPath, "hdc", DiskDef.diskBus.IDE, DiskDef.diskFmtType.RAW); + hdc.setDeviceType(DiskDef.deviceType.CDROM); disks.add(hdc); return disks; } - private List createVMDisk(List vols, String guestOSType, String isoURI) throws InternalErrorException, LibvirtException, URISyntaxException{ - List disks = new ArrayList(); + private List createVMDisk(List vols, String guestOSType, String isoURI) throws InternalErrorException, LibvirtException, URISyntaxException{ + List disks = new ArrayList(); // Get the root volume List rootVolumes = findVolumes(vols, VolumeType.ROOT, true); @@ -3505,17 +3796,17 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv if (dataVolumes.size() > 0) dataVolume = dataVolumes.get(0); - diskDef.diskBus diskBusType = getGuestDiskModel(guestOSType); + DiskDef.diskBus diskBusType = getGuestDiskModel(guestOSType); - diskDef hda = new diskDef(); - hda.defFileBasedDisk(rootVolume.getPath(), "vda", diskBusType, diskDef.diskFmtType.QCOW2); + DiskDef hda = new DiskDef(); + hda.defFileBasedDisk(rootVolume.getPath(), "vda", diskBusType, DiskDef.diskFmtType.QCOW2); disks.add(hda); /*Centos doesn't support scsi hotplug. For other host OSes, we attach the disk after the vm is running, so that we can hotplug it.*/ if (dataVolume != null) { - diskDef hdb = new diskDef(); - hdb.defFileBasedDisk(dataVolume.getPath(), "vdb", diskBusType, diskDef.diskFmtType.QCOW2); + DiskDef hdb = new DiskDef(); + hdb.defFileBasedDisk(dataVolume.getPath(), "vdb", diskBusType, DiskDef.diskFmtType.QCOW2); if (!isCentosHost()) { hdb.setAttachDeferred(true); } @@ -3523,9 +3814,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv } /*Add a placeholder for iso, even if there is no iso attached*/ - diskDef hdc = new diskDef(); - hdc.defFileBasedDisk(isoPath, "hdc", diskDef.diskBus.IDE, diskDef.diskFmtType.RAW); - hdc.setDeviceType(diskDef.deviceType.CDROM); + DiskDef hdc = new DiskDef(); + hdc.defFileBasedDisk(isoPath, "hdc", DiskDef.diskBus.IDE, DiskDef.diskFmtType.RAW); + hdc.setDeviceType(DiskDef.deviceType.CDROM); disks.add(hdc); return disks; diff --git a/agent/src/com/cloud/agent/resource/computing/LibvirtVMDef.java b/agent/src/com/cloud/agent/resource/computing/LibvirtVMDef.java index 4d0ab0ccbcc..f6c78e9155d 100644 --- a/agent/src/com/cloud/agent/resource/computing/LibvirtVMDef.java +++ b/agent/src/com/cloud/agent/resource/computing/LibvirtVMDef.java @@ -19,7 +19,10 @@ package com.cloud.agent.resource.computing; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; public class LibvirtVMDef { @@ -27,9 +30,9 @@ public class LibvirtVMDef { private String _domName; private String _domUUID; private String _desc; - private final List components = new ArrayList(); + private final Map components = new HashMap(); - public static class guestDef { + public static class GuestDef { enum guestType { KVM, XEN, @@ -104,12 +107,12 @@ public class LibvirtVMDef { } } - public static class guestResourceDef { - private int _mem; + public static class GuestResourceDef { + private long _mem; private int _currentMem = -1; private String _memBacking; private int _vcpu = -1; - public void setMemorySize(int mem) { + public void setMemorySize(long mem) { _mem = mem; } public void setCurrentMem(int currMem) { @@ -138,7 +141,7 @@ public class LibvirtVMDef { } } - public static class featuresDef { + public static class FeaturesDef { private final List _features = new ArrayList(); public void addFeatures(String feature) { _features.add(feature); @@ -154,11 +157,11 @@ public class LibvirtVMDef { return feaBuilder.toString(); } } - public static class termPolicy { + public static class TermPolicy { private String _reboot; private String _powerOff; private String _crash; - public termPolicy() { + public TermPolicy() { _reboot = _powerOff = _crash = "destroy"; } public void setRebootPolicy(String rbPolicy) { @@ -180,11 +183,20 @@ public class LibvirtVMDef { } } - public static class devicesDef { + public static class DevicesDef { private String _emulator; - private final List devices = new ArrayList(); + private final Map> devices = new HashMap>(); public boolean addDevice(Object device) { - return devices.add(device); + Object dev = devices.get(device.getClass().toString()); + if (dev == null) { + List devs = new ArrayList(); + devs.add(device); + devices.put(device.getClass().toString(), devs); + } else { + List devs = (List)dev; + devs.add(device); + } + return true; } public void setEmulatorPath(String emulator) { _emulator = emulator; @@ -196,15 +208,24 @@ public class LibvirtVMDef { if (_emulator != null) { devicesBuilder.append("" + _emulator + "\n"); } - for (Object o : devices) { - devicesBuilder.append(o.toString()); + + for (List devs : devices.values()) { + for (Object dev : devs) { + devicesBuilder.append(dev.toString()); + } } devicesBuilder.append("\n"); return devicesBuilder.toString(); } + public List getDisks() { + return (List)devices.get(DiskDef.class.toString()); + } + public List getInterfaces() { + return (List)devices.get(InterfaceDef.class.toString()); + } } - public static class diskDef { + public static class DiskDef { enum deviceType { FLOOPY("floopy"), DISK("disk"), @@ -282,6 +303,33 @@ public class LibvirtVMDef { _bus = bus; } + private String getDevLabel(int devId, diskBus bus) { + char suffix = (char)('a' + devId); + if (bus == diskBus.SCSI) { + return "sd" + suffix; + } else if (bus == diskBus.VIRTIO) { + return "vd" + suffix; + } + return "hd" + suffix; + } + public void defFileBasedDisk(String filePath, int devId, diskBus bus, diskFmtType diskFmtType) { + + _diskType = diskType.FILE; + _deviceType = deviceType.DISK; + _sourcePath = filePath; + _diskLabel = getDevLabel(devId, bus); + _diskFmtType = diskFmtType; + _bus = bus; + + } + public void defISODisk(String volPath) { + _diskType = diskType.FILE; + _deviceType = deviceType.CDROM; + _sourcePath = volPath; + _diskLabel = "hdc"; + _diskFmtType = diskFmtType.RAW; + _bus = diskBus.IDE; + } public void defBlockBasedDisk(String diskName, String diskLabel, diskBus bus) { _diskType = diskType.BLOCK; _deviceType = deviceType.DISK; @@ -307,6 +355,19 @@ public class LibvirtVMDef { public String getDiskLabel() { return _diskLabel; } + public deviceType getDeviceType() { + return _deviceType; + } + public void setDiskPath(String volPath) { + this._sourcePath = volPath; + } + public diskBus getBusType() { + return _bus; + } + public int getDiskSeq() { + char suffix = this._diskLabel.charAt(this._diskLabel.length() - 1); + return suffix - 'a'; + } @Override public String toString() { StringBuilder diskBuilder = new StringBuilder(); @@ -342,7 +403,7 @@ public class LibvirtVMDef { } } - public static class interfaceDef { + public static class InterfaceDef { enum guestNetType { BRIDGE("bridge"), NETWORK("network"), @@ -415,6 +476,7 @@ public class LibvirtVMDef { public guestNetType getNetType() { return _netType; } + @Override public String toString() { StringBuilder netBuilder = new StringBuilder(); @@ -437,12 +499,12 @@ public class LibvirtVMDef { return netBuilder.toString(); } } - public static class consoleDef { + public static class ConsoleDef { private final String _ttyPath; private final String _type; private final String _source; private short _port = -1; - public consoleDef(String type, String path, String source, short port) { + public ConsoleDef(String type, String path, String source, short port) { _type = type; _ttyPath = path; _source = source; @@ -467,11 +529,11 @@ public class LibvirtVMDef { return consoleBuilder.toString(); } } - public static class serialDef { + public static class SerialDef { private final String _type; private final String _source; private short _port = -1; - public serialDef(String type, String source, short port) { + public SerialDef(String type, String source, short port) { _type = type; _source = source; _port = port; @@ -490,14 +552,14 @@ public class LibvirtVMDef { return serialBuidler.toString(); } } - public static class graphicDef { + public static class GraphicDef { private final String _type; private short _port = -2; private boolean _autoPort = false; private final String _listenAddr; private final String _passwd; private final String _keyMap; - public graphicDef(String type, short port, boolean auotPort, String listenAddr, String passwd, String keyMap) { + public GraphicDef(String type, short port, boolean auotPort, String listenAddr, String passwd, String keyMap) { _type = type; _port = port; _autoPort = auotPort; @@ -528,10 +590,10 @@ public class LibvirtVMDef { return graphicBuilder.toString(); } } - public static class inputDef { + public static class InputDef { private final String _type; /*tablet, mouse*/ private final String _bus; /*ps2, usb, xen*/ - public inputDef(String type, String bus) { + public InputDef(String type, String bus) { _type = type; _bus = bus; } @@ -558,8 +620,18 @@ public class LibvirtVMDef { public void setDomDescription(String desc) { _desc = desc; } - public boolean addComp(Object comp) { - return components.add(comp); + public String getGuestOSType() { + return _desc; + } + public void addComp(Object comp) { + components.put(comp.getClass().toString(), comp); + } + public DevicesDef getDevices() { + Object o = components.get(DevicesDef.class.toString()); + if (o != null) { + return (DevicesDef)o; + } + return null; } @Override public String toString() { @@ -572,7 +644,7 @@ public class LibvirtVMDef { if (_desc != null ) { vmBuilder.append("" + _desc + "\n"); } - for (Object o : components) { + for (Object o : components.values()) { vmBuilder.append(o.toString()); } vmBuilder.append("\n"); @@ -586,63 +658,63 @@ public class LibvirtVMDef { vm.setDomainName("testing"); vm.setDomUUID(UUID.randomUUID().toString()); - guestDef guest = new guestDef(); - guest.setGuestType(guestDef.guestType.KVM); + GuestDef guest = new GuestDef(); + guest.setGuestType(GuestDef.guestType.KVM); guest.setGuestArch("x86_64"); guest.setMachineType("pc-0.11"); - guest.setBootOrder(guestDef.bootOrder.HARDISK); + guest.setBootOrder(GuestDef.bootOrder.HARDISK); vm.addComp(guest); - guestResourceDef grd = new guestResourceDef(); + GuestResourceDef grd = new GuestResourceDef(); grd.setMemorySize(512*1024); grd.setVcpuNum(1); vm.addComp(grd); - featuresDef features = new featuresDef(); + FeaturesDef features = new FeaturesDef(); features.addFeatures("pae"); features.addFeatures("apic"); features.addFeatures("acpi"); vm.addComp(features); - termPolicy term = new termPolicy(); + TermPolicy term = new TermPolicy(); term.setCrashPolicy("destroy"); term.setPowerOffPolicy("destroy"); term.setRebootPolicy("destroy"); vm.addComp(term); - devicesDef devices = new devicesDef(); + DevicesDef devices = new DevicesDef(); devices.setEmulatorPath("/usr/bin/cloud-qemu-system-x86_64"); - diskDef hda = new diskDef(); - hda.defFileBasedDisk("/path/to/hda1", "hda", diskDef.diskBus.IDE, diskDef.diskFmtType.QCOW2); + DiskDef hda = new DiskDef(); + hda.defFileBasedDisk("/path/to/hda1", 0, DiskDef.diskBus.VIRTIO, DiskDef.diskFmtType.QCOW2); devices.addDevice(hda); - diskDef hdb = new diskDef(); - hdb.defFileBasedDisk("/path/to/hda2", "hdb", diskDef.diskBus.IDE, diskDef.diskFmtType.QCOW2); + DiskDef hdb = new DiskDef(); + hdb.defFileBasedDisk("/path/to/hda2", 1, DiskDef.diskBus.VIRTIO, DiskDef.diskFmtType.QCOW2); devices.addDevice(hdb); - interfaceDef pubNic = new interfaceDef(); - pubNic.defBridgeNet("cloudbr0", "vnet1", "00:16:3e:77:e2:a1", interfaceDef.nicModel.VIRTIO); + InterfaceDef pubNic = new InterfaceDef(); + pubNic.defBridgeNet("cloudbr0", "vnet1", "00:16:3e:77:e2:a1", InterfaceDef.nicModel.VIRTIO); devices.addDevice(pubNic); - interfaceDef privNic = new interfaceDef(); - privNic.defPrivateNet("cloud-private", null, "00:16:3e:77:e2:a2", interfaceDef.nicModel.VIRTIO); + InterfaceDef privNic = new InterfaceDef(); + privNic.defPrivateNet("cloud-private", null, "00:16:3e:77:e2:a2", InterfaceDef.nicModel.VIRTIO); devices.addDevice(privNic); - interfaceDef vlanNic = new interfaceDef(); - vlanNic.defBridgeNet("vnbr1000", "tap1", "00:16:3e:77:e2:a2", interfaceDef.nicModel.VIRTIO); + InterfaceDef vlanNic = new InterfaceDef(); + vlanNic.defBridgeNet("vnbr1000", "tap1", "00:16:3e:77:e2:a2", InterfaceDef.nicModel.VIRTIO); devices.addDevice(vlanNic); - serialDef serial = new serialDef("pty", null, (short)0); + SerialDef serial = new SerialDef("pty", null, (short)0); devices.addDevice(serial); - consoleDef console = new consoleDef("pty", null, null, (short)0); + ConsoleDef console = new ConsoleDef("pty", null, null, (short)0); devices.addDevice(console); - graphicDef grap = new graphicDef("vnc", (short)0, true, null, null, null); + GraphicDef grap = new GraphicDef("vnc", (short)0, true, null, null, null); devices.addDevice(grap); - inputDef input = new inputDef("tablet", "usb"); + InputDef input = new InputDef("tablet", "usb"); devices.addDevice(input); vm.addComp(devices); diff --git a/api/src/com/cloud/vm/DiskProfile.java b/api/src/com/cloud/vm/DiskProfile.java index 7cfbedb1118..d17f06a5878 100644 --- a/api/src/com/cloud/vm/DiskProfile.java +++ b/api/src/com/cloud/vm/DiskProfile.java @@ -37,8 +37,8 @@ public class DiskProfile { private long diskOfferingId; private Long templateId; private long volumeId; - private Volume vol; - private DiskOffering offering; + + private HypervisorType hyperType; protected DiskProfile() { @@ -58,8 +58,6 @@ public class DiskProfile { 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/core/src/com/cloud/storage/VolumeVO.java b/core/src/com/cloud/storage/VolumeVO.java index b755376c3cd..d3b02e0f95e 100755 --- a/core/src/com/cloud/storage/VolumeVO.java +++ b/core/src/com/cloud/storage/VolumeVO.java @@ -238,7 +238,6 @@ public class VolumeVO implements Volume { } - public boolean isRecreatable() { return recreatable; } diff --git a/core/src/com/cloud/vm/SecondaryStorageVmVO.java b/core/src/com/cloud/vm/SecondaryStorageVmVO.java index 146875b4461..a97f690638e 100644 --- a/core/src/com/cloud/vm/SecondaryStorageVmVO.java +++ b/core/src/com/cloud/vm/SecondaryStorageVmVO.java @@ -89,7 +89,8 @@ public class SecondaryStorageVmVO extends VMInstanceVO implements SecondaryStora @Column(name="last_update", updatable=true, nullable=true) private Date lastUpdateTime; - public SecondaryStorageVmVO(long id, long serviceOfferingId, String name, long templateId, long guestOSId, long dataCenterId, long domainId, long accountId) { + public SecondaryStorageVmVO(long id, long serviceOfferingId, String name, long templateId, long guestOSId, long dataCenterId, + long domainId, long accountId) { super(id, serviceOfferingId, name, name, Type.SecondaryStorageVm, templateId, guestOSId, domainId, accountId, true); } diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 369de47ef6b..f11991cc209 100644 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -531,7 +531,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; @@ -927,7 +927,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) { diff --git a/server/src/com/cloud/hypervisor/KVMGuru.java b/server/src/com/cloud/hypervisor/KVMGuru.java new file mode 100644 index 00000000000..32527dc5b88 --- /dev/null +++ b/server/src/com/cloud/hypervisor/KVMGuru.java @@ -0,0 +1,37 @@ +package com.cloud.hypervisor; + +import javax.ejb.Local; + +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.GuestOSVO; +import com.cloud.storage.dao.GuestOSDao; +import com.cloud.utils.component.Inject; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; + +@Local(value=HypervisorGuru.class) +public class KVMGuru extends HypervisorGuruBase implements HypervisorGuru { + @Inject GuestOSDao _guestOsDao; + @Override + public HypervisorType getHypervisorType() { + return HypervisorType.KVM; + } + + protected KVMGuru() { + super(); + } + + @Override + public VirtualMachineTO implement( + VirtualMachineProfile vm) { + VirtualMachineTO to = toVirtualMachineTO(vm); + + // Determine the VM's OS description + GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId()); + to.setOs(guestOS.getDisplayName()); + + return to; + } + +} diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java index 347ad67d331..76079f6b9ea 100644 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java @@ -17,6 +17,7 @@ */ package com.cloud.storage.secondary; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Date; import java.util.Enumeration; @@ -49,6 +50,9 @@ import com.cloud.agent.api.StartSecStorageVmCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StopAnswer; import com.cloud.agent.api.StopCommand; +import com.cloud.agent.api.check.CheckSshAnswer; +import com.cloud.agent.api.check.CheckSshCommand; +import com.cloud.agent.manager.Commands; import com.cloud.async.AsyncJobExecutor; import com.cloud.async.AsyncJobManager; import com.cloud.async.AsyncJobVO; @@ -65,6 +69,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.domain.DomainVO; import com.cloud.event.EventState; import com.cloud.event.EventTypes; @@ -87,6 +92,7 @@ import com.cloud.info.RunningHostInfoAgregator.ZoneHostInfo; import com.cloud.network.IpAddrAllocator; import com.cloud.network.NetworkConfigurationVO; import com.cloud.network.IpAddrAllocator.networkInfo; +import com.cloud.network.Network.TrafficType; import com.cloud.network.NetworkManager; import com.cloud.network.dao.IPAddressDao; import com.cloud.offering.NetworkOffering; @@ -127,11 +133,15 @@ import com.cloud.utils.events.SubscriptionMgr; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.ExecutionException; import com.cloud.utils.net.NetUtils; +import com.cloud.utils.net.NfsUtils; import com.cloud.vm.ConsoleProxyVO; import com.cloud.vm.NicProfile; +import com.cloud.vm.ReservationContext; import com.cloud.vm.SecondaryStorageVmVO; import com.cloud.vm.State; import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineGuru; +import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.VmManager; import com.cloud.vm.VirtualMachine.Event; import com.cloud.vm.VirtualMachineManager; @@ -159,7 +169,7 @@ import com.cloud.vm.dao.VMInstanceDao; // because sooner or later, it will be driven into Running state // @Local(value={SecondaryStorageVmManager.class}) -public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, VirtualMachineManager { +public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, VirtualMachineManager, VirtualMachineGuru { private static final Logger s_logger = Logger.getLogger(SecondaryStorageManagerImpl.class); private static final int DEFAULT_FIND_HOST_RETRY_COUNT = 2; @@ -236,6 +246,8 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V private String _instance; private boolean _useLocalStorage; private boolean _useSSlCopy; + private String _secHostUuid; + private String _nfsShare; private String _allowedInternalSites; @@ -686,7 +698,8 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V return null; } - SecondaryStorageVmVO secStorageVm = allocSecStorageVmStorage(dataCenterId, secStorageVmId); + SecondaryStorageVmVO secStorageVm = _secStorageVmDao.findById(secStorageVmId); + //SecondaryStorageVmVO secStorageVm = allocSecStorageVmStorage(dataCenterId, secStorageVmId); if (secStorageVm != null) { SubscriptionMgr.getInstance().notifySubscribers(ALERT_SUBJECT, this, new SecStorageVmAlertEventArgs( @@ -710,7 +723,18 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V } protected Map createSecStorageVmInstance2(long dataCenterId) { - + long startEventId = saveStartedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_CREATE, "Creating secondary storage Vm in zone : "+dataCenterId, 0); + HostVO secHost = _hostDao.findSecondaryStorageHost(dataCenterId); + if (secHost == null) { + String msg = "No secondary storage available in zone " + dataCenterId + ", cannot create secondary storage vm"; + s_logger.warn(msg); + saveFailedEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, EventTypes.EVENT_SSVM_CREATE, msg, startEventId); + throw new CloudRuntimeException(msg); + } + + _secHostUuid = secHost.getGuid(); + _nfsShare = secHost.getStorageUrl(); + long id = _secStorageVmDao.getNextInSequence(Long.class, "id"); String name = VirtualMachineName.getSystemVmName(id, _instance, "s").intern(); AccountVO systemAcct = _accountMgr.getSystemAccount(); @@ -1434,12 +1458,15 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V haMgr.registerHandler(VirtualMachine.Type.SecondaryStorageVm, this); } + _itMgr.registerGuru(VirtualMachine.Type.SecondaryStorageVm, this); + Adapters ipAllocators = locator.getAdapters(IpAddrAllocator.class); if (ipAllocators != null && ipAllocators.isSet()) { Enumeration it = ipAllocators.enumeration(); _IpAllocator = it.nextElement(); } + boolean useLocalStorage = Boolean.parseBoolean(configs.get(Config.SystemVMUseLocalStorage.key())); String networkRateStr = _configDao.getValue("network.throttling.rate"); String multicastRateStr = _configDao.getValue("multicast.throttling.rate"); @@ -1963,4 +1990,110 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V _eventDao.persist(event); return; } + + @Override + public SecondaryStorageVmVO findByName(String name) { + if (!VirtualMachineName.isValidSecStorageVmName(name, null)) { + return null; + } + return findById(VirtualMachineName.getSystemVmId(name)); + } + + @Override + public SecondaryStorageVmVO findById(long id) { + return _secStorageVmDao.findById(id); + } + + @Override + public SecondaryStorageVmVO persist(SecondaryStorageVmVO vm) { + return _secStorageVmDao.persist(vm); + } + + @Override + public boolean finalizeVirtualMachineProfile( + VirtualMachineProfile profile, + DeployDestination dest, ReservationContext context) { + + StringBuilder buf = profile.getBootArgsBuilder(); + buf.append(" template=domP type=secstorage"); + buf.append(" host=").append(_mgmt_host); + buf.append(" port=").append(_mgmt_port); + buf.append(" name=").append(profile.getVirtualMachine().getHostName()); + + buf.append(" zone=").append(dest.getDataCenter().getId()); + buf.append(" pod=").append(dest.getPod().getId()); + buf.append(" guid=").append(_secHostUuid); + buf.append(" mount.path=").append(_nfsShare); + buf.append(" resource=com.cloud.storage.resource.NfsSecondaryStorageResource"); + buf.append(" instance=SecStorage"); + buf.append(" sslcopy=").append(Boolean.toString(_useSSlCopy)); + + NicProfile controlNic = null; + for (NicProfile nic : profile.getNics()) { + int deviceId = nic.getDeviceId(); + if (nic.getIp4Address() == null) { + /*External DHCP mode*/ + buf.append(" eth").append(deviceId).append("ip=").append("0.0.0.0"); + buf.append(" bootproto=dhcp"); + } else { + buf.append(" eth").append(deviceId).append("ip=").append(nic.getIp4Address()); + } + + 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()); + } + } + if (nic.getTrafficType() == TrafficType.Management) { + buf.append(" localgw=").append(dest.getPod().getGateway()); + } else if (nic.getTrafficType() == TrafficType.Control) { + controlNic = nic; + } + + } + + String bootArgs = buf.toString(); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Boot Args for " + profile + ": " + bootArgs); + } + + if (controlNic == null) { + throw new CloudRuntimeException("Didn't start a control port"); + } + + profile.setParameter("control.nic", controlNic); + + return true; + } + + @Override + public boolean finalizeDeployment(Commands cmds, + VirtualMachineProfile profile, + DeployDestination dest, ReservationContext context) { + NicProfile controlNic = (NicProfile)profile.getParameter("control.nic"); + CheckSshCommand check = new CheckSshCommand(profile.getInstanceName(), controlNic.getIp4Address(), 3922, 5, 20); + cmds.addCommand("checkSsh", check); + return true; + } + + @Override + public boolean finalizeStart(Commands cmds, + VirtualMachineProfile profile, + DeployDestination dest, ReservationContext context) { + CheckSshAnswer answer = (CheckSshAnswer)cmds.getAnswer("checkSsh"); + if (!answer.getResult()) { + s_logger.warn("Unable to ssh to the VM: " + answer.getDetails()); + return false; + } + return true; + } + + @Override + public void finalizeStop( + VirtualMachineProfile profile, long hostId, + String reservationId) { + } } diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 91c0e1276e0..fed523c8d63 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -740,17 +740,17 @@ CREATE TABLE `cloud`.`secondary_storage_vm` ( `dns1` varchar(15) COMMENT 'dns1', `dns2` varchar(15) COMMENT 'dns2', `domain` varchar(255) COMMENT 'domain', - `public_mac_address` varchar(17) NOT NULL unique COMMENT 'mac address of the public facing network card', + `public_mac_address` varchar(17) unique COMMENT 'mac address of the public facing network card', `public_ip_address` varchar(15) UNIQUE COMMENT 'public ip address for the sec storage vm', `public_netmask` varchar(15) COMMENT 'public netmask used for the sec storage vm', - `guest_mac_address` varchar(17) NOT NULL unique COMMENT 'mac address of the guest facing network card', + `guest_mac_address` varchar(17) unique COMMENT 'mac address of the guest facing network card', `guest_ip_address` varchar(15) UNIQUE COMMENT 'guest ip address for the console proxy', `guest_netmask` varchar(15) COMMENT 'guest netmask used for the console proxy', `vlan_db_id` bigint unsigned COMMENT 'Foreign key into vlan id table', `vlan_id` varchar(255) COMMENT 'optional VLAN ID for sec storage vm that can be used', `ram_size` int(10) unsigned NOT NULL DEFAULT 512 COMMENT 'memory to use in mb', - `guid` varchar(255) NOT NULL COMMENT 'copied from guid of secondary storage host', - `nfs_share` varchar(255) NOT NULL COMMENT 'server and path exported by the nfs server ', + `guid` varchar(255) COMMENT 'copied from guid of secondary storage host', + `nfs_share` varchar(255) COMMENT 'server and path exported by the nfs server ', `last_update` DATETIME NULL COMMENT 'Last session update time', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;