mirror of https://github.com/apache/cloudstack.git
CLOUDSTACK-922: LXC Support in Cloudstack.
Signed-off-by: Edison Su <sudison@gmail.com>
This commit is contained in:
parent
6eac422943
commit
aa79ccf985
|
|
@ -80,3 +80,12 @@ domr.scripts.dir=scripts/network/domr/kvm
|
|||
# native = com.cloud.hypervisor.kvm.resource.BridgeVifDriver
|
||||
# openvswitch = com.cloud.hypervisor.kvm.resource.OvsBridgeDriver
|
||||
#libvirt.vif.driver=com.cloud.hypervisor.kvm.resource.BridgeVifDriver
|
||||
|
||||
# set the hypervisor type, values are: kvm, lxc
|
||||
# hypervisor.type=kvm
|
||||
|
||||
# settings to enable direct networking in libvirt, should not be used
|
||||
# on hosts that run system vms, values for mode are: private, bridge, vepa
|
||||
# libvirt.vif.driver=com.cloud.hypervisor.kvm.resource.DirectVifDriver
|
||||
# network.direct.source.mode=private
|
||||
# network.direct.device=eth0
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ import com.cloud.agent.api.LogLevel.Log4jLevel;
|
|||
*/
|
||||
public abstract class Command {
|
||||
|
||||
public static final String HYPERVISOR_TYPE = "hypervisorType";
|
||||
|
||||
// allow command to carry over hypervisor or other environment related context info
|
||||
@LogLevel(Log4jLevel.Trace)
|
||||
protected Map<String, String> contextMap = new HashMap<String, String>();
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
// under the License.
|
||||
package com.cloud.agent.api;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
|
||||
public class RebootCommand extends Command {
|
||||
|
|
|
|||
|
|
@ -38,10 +38,9 @@ public class StopCommand extends RebootCommand {
|
|||
super(vm);
|
||||
this.vnet = vnet;
|
||||
}
|
||||
|
||||
public StopCommand(VirtualMachine vm, String vmName, String vnet) {
|
||||
super(vmName);
|
||||
this.vnet = vnet;
|
||||
|
||||
public StopCommand(VirtualMachine vm) {
|
||||
super(vm);
|
||||
}
|
||||
|
||||
public StopCommand(String vmName) {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ public class Hypervisor {
|
|||
BareMetal,
|
||||
Simulator,
|
||||
Ovm,
|
||||
LXC,
|
||||
|
||||
Any; /*If you don't care about the hypervisor type*/
|
||||
|
||||
|
|
@ -54,6 +55,8 @@ public class Hypervisor {
|
|||
return HypervisorType.Simulator;
|
||||
} else if (hypervisor.equalsIgnoreCase("Ovm")) {
|
||||
return HypervisorType.Ovm;
|
||||
} else if (hypervisor.equalsIgnoreCase("LXC")) {
|
||||
return HypervisorType.LXC;
|
||||
} else if (hypervisor.equalsIgnoreCase("Any")) {
|
||||
return HypervisorType.Any;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ public class Storage {
|
|||
VHD(true, true, true),
|
||||
ISO(false, false, false),
|
||||
OVA(true, true, true, "ova"),
|
||||
BAREMETAL(false, false, false);
|
||||
BAREMETAL(false, false, false),
|
||||
TAR(false, false, false);
|
||||
|
||||
private final boolean thinProvisioned;
|
||||
private final boolean supportSparse;
|
||||
|
|
|
|||
|
|
@ -499,6 +499,10 @@
|
|||
<property name="name" value="KVM Agent"/>
|
||||
</bean>
|
||||
|
||||
<bean id="LxcServerDiscoverer" class="com.cloud.hypervisor.kvm.discoverer.LxcServerDiscoverer">
|
||||
<property name="name" value="Lxc Discover"/>
|
||||
</bean>
|
||||
|
||||
<bean id="HypervServerDiscoverer" class="com.cloud.hypervisor.hyperv.HypervServerDiscoverer">
|
||||
<property name="name" value="SCVMMServer"/>
|
||||
</bean>
|
||||
|
|
@ -568,6 +572,10 @@
|
|||
<property name="name" value="KVMGuru"/>
|
||||
</bean>
|
||||
|
||||
<bean id="LXCGuru" class="com.cloud.hypervisor.LXCGuru">
|
||||
<property name="name" value="LXCGuru"/>
|
||||
</bean>
|
||||
|
||||
<bean id="OvmGuru" class="com.cloud.ovm.hypervisor.OvmGuru">
|
||||
<property name="name" value="OvmGuru"/>
|
||||
</bean>
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@
|
|||
<ref bean="XcpServerDiscoverer"/>
|
||||
<ref bean="SecondaryStorageDiscoverer"/>
|
||||
<ref bean="KvmServerDiscoverer"/>
|
||||
<ref bean="LxcServerDiscoverer"/>
|
||||
|
||||
<!--
|
||||
<ref bean="BareMetalDiscoverer"/>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package com.cloud.hypervisor.kvm.resource;
|
||||
|
||||
import com.cloud.agent.api.to.NicTO;
|
||||
import com.cloud.exception.InternalErrorException;
|
||||
import com.cloud.network.Networks;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.libvirt.LibvirtException;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
import java.util.Map;
|
||||
|
||||
public class DirectVifDriver extends VifDriverBase {
|
||||
|
||||
private static final Logger s_logger = Logger.getLogger(DirectVifDriver.class);
|
||||
|
||||
/**
|
||||
* Experimental driver to configure direct networking in libvirt. This should only
|
||||
* be used on an LXC cluster that does not run any system VMs.
|
||||
*
|
||||
* @param nic
|
||||
* @param guestOsType
|
||||
* @return
|
||||
* @throws InternalErrorException
|
||||
* @throws LibvirtException
|
||||
*/
|
||||
public LibvirtVMDef.InterfaceDef plug(NicTO nic, String guestOsType) throws InternalErrorException,
|
||||
LibvirtException {
|
||||
LibvirtVMDef.InterfaceDef intf = new LibvirtVMDef.InterfaceDef();
|
||||
|
||||
if (nic.getType() == Networks.TrafficType.Guest) {
|
||||
intf.defDirectNet(_libvirtComputingResource.getNetworkDirectDevice(), null, nic.getMac(), getGuestNicModel(guestOsType),
|
||||
_libvirtComputingResource.getNetworkDirectSourceMode());
|
||||
|
||||
} else if (nic.getType() == Networks.TrafficType.Public) {
|
||||
intf.defDirectNet(_libvirtComputingResource.getNetworkDirectDevice(), null, nic.getMac(), getGuestNicModel(guestOsType),
|
||||
_libvirtComputingResource.getNetworkDirectSourceMode());
|
||||
}
|
||||
|
||||
return intf;
|
||||
}
|
||||
|
||||
public void unplug(LibvirtVMDef.InterfaceDef iface) {
|
||||
// not needed, libvirt will cleanup
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -182,6 +182,7 @@ import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DevicesDef;
|
|||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DiskDef;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DiskDef.diskProtocol;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.FeaturesDef;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.FilesystemDef;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.GraphicDef;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.GuestDef;
|
||||
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.GuestResourceDef;
|
||||
|
|
@ -323,9 +324,11 @@ ServerResource {
|
|||
+ " <uuid>{1}</uuid>" + " </domain>"
|
||||
+ " </domainsnapshot>");
|
||||
|
||||
protected String _hypervisorType;
|
||||
protected HypervisorType _hypervisorType;
|
||||
protected String _hypervisorURI;
|
||||
protected String _hypervisorPath;
|
||||
protected String _networkDirectSourceMode;
|
||||
protected String _networkDirectDevice;
|
||||
protected String _sysvmISOPath;
|
||||
protected String _privNwName;
|
||||
protected String _privBridgeName;
|
||||
|
|
@ -392,6 +395,7 @@ ServerResource {
|
|||
|
||||
private Map<String, Object> getDeveloperProperties()
|
||||
throws ConfigurationException {
|
||||
|
||||
final File file = PropertiesUtil.findConfigFile("developer.properties");
|
||||
if (file == null) {
|
||||
throw new ConfigurationException(
|
||||
|
|
@ -447,6 +451,14 @@ ServerResource {
|
|||
return "scripts/network/domr/kvm";
|
||||
}
|
||||
|
||||
protected String getNetworkDirectSourceMode() {
|
||||
return _networkDirectSourceMode;
|
||||
}
|
||||
|
||||
protected String getNetworkDirectDevice() {
|
||||
return _networkDirectDevice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params)
|
||||
throws ConfigurationException {
|
||||
|
|
@ -586,15 +598,19 @@ ServerResource {
|
|||
|
||||
String instance = (String) params.get("instance");
|
||||
|
||||
_hypervisorType = (String) params.get("hypervisor.type");
|
||||
if (_hypervisorType == null) {
|
||||
_hypervisorType = "kvm";
|
||||
_hypervisorType = HypervisorType.getType((String) params.get("hypervisor.type"));
|
||||
if (_hypervisorType == HypervisorType.None) {
|
||||
_hypervisorType = HypervisorType.KVM;
|
||||
}
|
||||
|
||||
_hypervisorURI = (String) params.get("hypervisor.uri");
|
||||
if (_hypervisorURI == null) {
|
||||
_hypervisorURI = "qemu:///system";
|
||||
_hypervisorURI = LibvirtConnection.getHypervisorURI(_hypervisorType.toString());
|
||||
}
|
||||
|
||||
_networkDirectSourceMode = (String) params.get("network.direct.source.mode");
|
||||
_networkDirectDevice = (String) params.get("network.direct.device");
|
||||
|
||||
String startMac = (String) params.get("private.macaddr.start");
|
||||
if (startMac == null) {
|
||||
startMac = "00:16:3e:77:e2:a0";
|
||||
|
|
@ -680,12 +696,14 @@ ServerResource {
|
|||
throw new CloudRuntimeException(e.getMessage());
|
||||
}
|
||||
|
||||
/* Does node support HVM guest? If not, exit */
|
||||
if (!IsHVMEnabled(conn)) {
|
||||
throw new ConfigurationException(
|
||||
"NO HVM support on this machine, please make sure: "
|
||||
+ "1. VT/SVM is supported by your CPU, or is enabled in BIOS. "
|
||||
+ "2. kvm modules are loaded (kvm, kvm_amd|kvm_intel)");
|
||||
if (HypervisorType.KVM == _hypervisorType) {
|
||||
/* Does node support HVM guest? If not, exit */
|
||||
if (!IsHVMEnabled(conn)) {
|
||||
throw new ConfigurationException(
|
||||
"NO HVM support on this machine, please make sure: "
|
||||
+ "1. VT/SVM is supported by your CPU, or is enabled in BIOS. "
|
||||
+ "2. kvm modules are loaded (kvm, kvm_amd|kvm_intel)");
|
||||
}
|
||||
}
|
||||
|
||||
_hypervisorPath = getHypervisorPath(conn);
|
||||
|
|
@ -1514,7 +1532,7 @@ ServerResource {
|
|||
NicTO nic = cmd.getNic();
|
||||
String vmName = cmd.getVmName();
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnection();
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
|
||||
Domain vm = getDomain(conn, vmName);
|
||||
List<InterfaceDef> pluggedNics = getInterfaces(conn, vmName);
|
||||
Integer nicnum = 0;
|
||||
|
|
@ -1543,7 +1561,7 @@ ServerResource {
|
|||
NicTO nic = cmd.getNic();
|
||||
String vmName = cmd.getInstanceName();
|
||||
try {
|
||||
conn = LibvirtConnection.getConnection();
|
||||
conn = LibvirtConnection.getConnectionByVmName(vmName);
|
||||
Domain vm = getDomain(conn, vmName);
|
||||
List<InterfaceDef> pluggedNics = getInterfaces(conn, vmName);
|
||||
for (InterfaceDef pluggedNic : pluggedNics) {
|
||||
|
|
@ -1581,7 +1599,7 @@ ServerResource {
|
|||
}
|
||||
|
||||
try {
|
||||
conn = LibvirtConnection.getConnection();
|
||||
conn = LibvirtConnection.getConnectionByVmName(routerName);
|
||||
Domain vm = getDomain(conn, routerName);
|
||||
List<InterfaceDef> pluggedNics = getInterfaces(conn, routerName);
|
||||
InterfaceDef routerNic = null;
|
||||
|
|
@ -1622,7 +1640,7 @@ ServerResource {
|
|||
String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
|
||||
|
||||
try {
|
||||
conn = LibvirtConnection.getConnection();
|
||||
conn = LibvirtConnection.getConnectionByVmName(routerName);
|
||||
Domain vm = getDomain(conn, routerName);
|
||||
String [][] rules = cmd.generateFwRules();
|
||||
String[] aclRules = rules[0];
|
||||
|
|
@ -1661,7 +1679,7 @@ ServerResource {
|
|||
IpAddressTO pubIP = cmd.getIpAddress();
|
||||
|
||||
try {
|
||||
conn = LibvirtConnection.getConnection();
|
||||
conn = LibvirtConnection.getConnectionByVmName(routerName);
|
||||
Domain vm = getDomain(conn, routerName);
|
||||
Integer devNum = 0;
|
||||
String pubVlan = pubIP.getVlanId();
|
||||
|
|
@ -1707,7 +1725,7 @@ ServerResource {
|
|||
String routerIP = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP);
|
||||
|
||||
try {
|
||||
conn = LibvirtConnection.getConnection();
|
||||
conn = LibvirtConnection.getConnectionByVmName(routerName);
|
||||
IpAddressTO[] ips = cmd.getIpAddresses();
|
||||
Domain vm = getDomain(conn, routerName);
|
||||
Integer devNum = 0;
|
||||
|
|
@ -1755,7 +1773,7 @@ ServerResource {
|
|||
String[] results = new String[cmd.getIpAddresses().length];
|
||||
Connect conn;
|
||||
try {
|
||||
conn = LibvirtConnection.getConnection();
|
||||
conn = LibvirtConnection.getConnectionByVmName(routerName);
|
||||
List<InterfaceDef> nics = getInterfaces(conn, routerName);
|
||||
Map<String, Integer> vlanAllocatedToVM = new HashMap<String, Integer>();
|
||||
Integer nicPos = 0;
|
||||
|
|
@ -1812,7 +1830,7 @@ ServerResource {
|
|||
String snapshotPath = cmd.getSnapshotPath();
|
||||
String vmName = cmd.getVmName();
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnection();
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
|
||||
DomainInfo.DomainState state = null;
|
||||
Domain vm = null;
|
||||
if (vmName != null) {
|
||||
|
|
@ -1901,7 +1919,7 @@ ServerResource {
|
|||
String vmName = cmd.getVmName();
|
||||
KVMStoragePool secondaryStoragePool = null;
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnection();
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
|
||||
|
||||
secondaryStoragePool = _storagePoolMgr.getStoragePoolByURI(
|
||||
secondaryStoragePoolUrl);
|
||||
|
|
@ -2170,7 +2188,7 @@ ServerResource {
|
|||
KVMStoragePool secondaryStorage = null;
|
||||
KVMStoragePool primary = null;
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnection();
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
||||
String templateFolder = cmd.getAccountId() + File.separator
|
||||
+ cmd.getTemplateId() + File.separator;
|
||||
String templateInstallFolder = "/template/tmpl/" + templateFolder;
|
||||
|
|
@ -2357,7 +2375,7 @@ ServerResource {
|
|||
String vif = null;
|
||||
String brname = null;
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnection();
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
||||
List<InterfaceDef> nics = getInterfaces(conn, cmd.getVmName());
|
||||
vif = nics.get(0).getDevName();
|
||||
brname = nics.get(0).getBrName();
|
||||
|
|
@ -2391,7 +2409,7 @@ ServerResource {
|
|||
|
||||
protected GetVncPortAnswer execute(GetVncPortCommand cmd) {
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnection();
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getName());
|
||||
Integer vncPort = getVncPort(conn, cmd.getName());
|
||||
return new GetVncPortAnswer(cmd, _privateIp, 5900 + vncPort);
|
||||
} catch (LibvirtException e) {
|
||||
|
|
@ -2462,7 +2480,7 @@ ServerResource {
|
|||
|
||||
private Answer execute(AttachIsoCommand cmd) {
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnection();
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
||||
attachOrDetachISO(conn, cmd.getVmName(), cmd.getIsoPath(),
|
||||
cmd.isAttach());
|
||||
} catch (LibvirtException e) {
|
||||
|
|
@ -2478,7 +2496,7 @@ ServerResource {
|
|||
|
||||
private AttachVolumeAnswer execute(AttachVolumeCommand cmd) {
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnection();
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
||||
KVMStoragePool primary = _storagePoolMgr.getStoragePool(
|
||||
cmd.getPooltype(),
|
||||
cmd.getPoolUuid());
|
||||
|
|
@ -2530,7 +2548,7 @@ ServerResource {
|
|||
|
||||
private Answer execute(CheckVirtualMachineCommand cmd) {
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnection();
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
||||
final State state = getVmState(conn, cmd.getVmName());
|
||||
Integer vncPort = null;
|
||||
if (state == State.Running) {
|
||||
|
|
@ -2599,7 +2617,7 @@ ServerResource {
|
|||
Domain destDomain = null;
|
||||
Connect conn = null;
|
||||
try {
|
||||
conn = LibvirtConnection.getConnection();
|
||||
conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
||||
ifaces = getInterfaces(conn, vmName);
|
||||
dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName
|
||||
.getBytes()));
|
||||
|
|
@ -2659,7 +2677,7 @@ ServerResource {
|
|||
|
||||
NicTO[] nics = vm.getNics();
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnection();
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(vm.getName());
|
||||
for (NicTO nic : nics) {
|
||||
getVifDriver(nic.getType()).plug(nic, null);
|
||||
}
|
||||
|
|
@ -2854,7 +2872,7 @@ ServerResource {
|
|||
}
|
||||
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnection();
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
||||
final String result = rebootVM(conn, cmd.getVmName());
|
||||
if (result == null) {
|
||||
Integer vncPort = null;
|
||||
|
|
@ -2892,8 +2910,8 @@ ServerResource {
|
|||
List<String> vmNames = cmd.getVmNames();
|
||||
try {
|
||||
HashMap<String, VmStatsEntry> vmStatsNameMap = new HashMap<String, VmStatsEntry>();
|
||||
Connect conn = LibvirtConnection.getConnection();
|
||||
for (String vmName : vmNames) {
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
|
||||
VmStatsEntry statEntry = getVmStat(conn, vmName);
|
||||
if (statEntry == null) {
|
||||
continue;
|
||||
|
|
@ -2917,7 +2935,7 @@ ServerResource {
|
|||
_vms.put(vmName, State.Stopping);
|
||||
}
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnection();
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(vmName);
|
||||
|
||||
List<DiskDef> disks = getDisks(conn, vmName);
|
||||
List<InterfaceDef> ifaces = getInterfaces(conn, vmName);
|
||||
|
|
@ -3047,14 +3065,22 @@ ServerResource {
|
|||
|
||||
protected 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(vmTO.getOs());
|
||||
|
||||
GuestDef guest = new GuestDef();
|
||||
guest.setGuestType(GuestDef.guestType.KVM);
|
||||
|
||||
if (HypervisorType.LXC == _hypervisorType &&
|
||||
VirtualMachine.Type.User == vmTO.getType()) {
|
||||
// LXC domain is only valid for user VMs. Use KVM for system VMs.
|
||||
guest.setGuestType(GuestDef.guestType.LXC);
|
||||
vm.setHvsType(HypervisorType.LXC.toString().toLowerCase());
|
||||
} else {
|
||||
guest.setGuestType(GuestDef.guestType.KVM);
|
||||
vm.setHvsType(HypervisorType.KVM.toString().toLowerCase());
|
||||
}
|
||||
guest.setGuestArch(vmTO.getArch());
|
||||
guest.setMachineType("pc");
|
||||
guest.setBootOrder(GuestDef.bootOrder.CDROM);
|
||||
|
|
@ -3115,6 +3141,7 @@ ServerResource {
|
|||
|
||||
DevicesDef devices = new DevicesDef();
|
||||
devices.setEmulatorPath(_hypervisorPath);
|
||||
devices.setGuestType(guest.getGuestType());
|
||||
|
||||
SerialDef serial = new SerialDef("pty", null, (short) 0);
|
||||
devices.addDevice(serial);
|
||||
|
|
@ -3160,13 +3187,14 @@ ServerResource {
|
|||
State state = State.Stopped;
|
||||
Connect conn = null;
|
||||
try {
|
||||
conn = LibvirtConnection.getConnection();
|
||||
synchronized (_vms) {
|
||||
_vms.put(vmName, State.Starting);
|
||||
}
|
||||
|
||||
vm = createVMFromSpec(vmSpec);
|
||||
|
||||
conn = LibvirtConnection.getConnectionByType(vm.getHvsType());
|
||||
|
||||
createVbd(conn, vmSpec, vmName, vm);
|
||||
|
||||
createVifs(vmSpec, vm);
|
||||
|
|
@ -3331,6 +3359,22 @@ ServerResource {
|
|||
vm.getDevices().addDevice(iso);
|
||||
}
|
||||
}
|
||||
|
||||
// For LXC, find and add the root filesystem
|
||||
if (HypervisorType.LXC.toString().toLowerCase().equals(vm.getHvsType())) {
|
||||
for (VolumeTO volume : disks) {
|
||||
if (volume.getType() == Volume.Type.ROOT) {
|
||||
KVMStoragePool pool = _storagePoolMgr.getStoragePool(
|
||||
volume.getPoolType(),
|
||||
volume.getPoolUuid());
|
||||
KVMPhysicalDisk physicalDisk = pool.getPhysicalDisk(volume.getPath());
|
||||
FilesystemDef rootFs = new FilesystemDef(physicalDisk.getPath(), "/");
|
||||
vm.getDevices().addDevice(rootFs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private VolumeTO getVolume(VirtualMachineTO vmSpec, Volume.Type type) {
|
||||
|
|
@ -3565,7 +3609,7 @@ ServerResource {
|
|||
|
||||
final StartupRoutingCommand cmd = new StartupRoutingCommand(
|
||||
(Integer) info.get(0), (Long) info.get(1), (Long) info.get(2),
|
||||
(Long) info.get(4), (String) info.get(3), HypervisorType.KVM,
|
||||
(Long) info.get(4), (String) info.get(3), _hypervisorType,
|
||||
RouterPrivateIpStrategy.HostLocal);
|
||||
cmd.setStateChanges(changes);
|
||||
fillNetworkInformation(cmd);
|
||||
|
|
@ -3721,7 +3765,7 @@ ServerResource {
|
|||
Domain dm = null;
|
||||
for (; i < 5; i++) {
|
||||
try {
|
||||
Connect conn = LibvirtConnection.getConnection();
|
||||
Connect conn = LibvirtConnection.getConnectionByVmName(vm);
|
||||
dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vm
|
||||
.getBytes()));
|
||||
DomainInfo.DomainState vps = dm.getInfo().state;
|
||||
|
|
@ -3793,16 +3837,30 @@ ServerResource {
|
|||
|
||||
private HashMap<String, State> getAllVms() {
|
||||
final HashMap<String, State> vmStates = new HashMap<String, State>();
|
||||
Connect conn = null;
|
||||
|
||||
try {
|
||||
conn = LibvirtConnection.getConnectionByType(HypervisorType.LXC.toString());
|
||||
vmStates.putAll(getAllVms(conn));
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.debug("Failed to get connection: " + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
conn = LibvirtConnection.getConnectionByType(HypervisorType.KVM.toString());
|
||||
vmStates.putAll(getAllVms(conn));
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.debug("Failed to get connection: " + e.getMessage());
|
||||
}
|
||||
|
||||
return vmStates;
|
||||
}
|
||||
|
||||
private HashMap<String, State> getAllVms(Connect conn) {
|
||||
final HashMap<String, State> vmStates = new HashMap<String, State>();
|
||||
|
||||
String[] vms = null;
|
||||
int[] ids = null;
|
||||
Connect conn = null;
|
||||
try {
|
||||
conn = LibvirtConnection.getConnection();
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.debug("Failed to get connection: " + e.getMessage());
|
||||
return vmStates;
|
||||
}
|
||||
|
||||
try {
|
||||
ids = conn.listDomains();
|
||||
|
|
@ -4253,9 +4311,11 @@ ServerResource {
|
|||
}
|
||||
|
||||
private void cleanupVMNetworks(Connect conn, List<InterfaceDef> nics) {
|
||||
for (InterfaceDef nic : nics) {
|
||||
if (nic.getHostNetType() == hostNicType.VNET) {
|
||||
cleanupVnet(conn, getVnetIdFromBrName(nic.getBrName()));
|
||||
if (nics != null) {
|
||||
for (InterfaceDef nic : nics) {
|
||||
if (nic.getHostNetType() == hostNicType.VNET) {
|
||||
cleanupVnet(conn, getVnetIdFromBrName(nic.getBrName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4467,7 +4527,7 @@ ServerResource {
|
|||
}
|
||||
|
||||
List<InterfaceDef> intfs = getInterfaces(conn, vmName);
|
||||
if (intfs.size() < nic.getDeviceId()) {
|
||||
if (intfs.size() == 0 || intfs.size() < nic.getDeviceId()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -4565,7 +4625,7 @@ ServerResource {
|
|||
cmd.add("--vif", vif);
|
||||
cmd.add("--brname", brname);
|
||||
cmd.add("--nicsecips", secIps);
|
||||
if (rules != null) {
|
||||
if (newRules != null && !newRules.isEmpty()) {
|
||||
cmd.add("--rules", newRules);
|
||||
}
|
||||
String result = cmd.execute();
|
||||
|
|
@ -4673,7 +4733,7 @@ ServerResource {
|
|||
boolean success = false;
|
||||
Connect conn;
|
||||
try {
|
||||
conn = LibvirtConnection.getConnection();
|
||||
conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
||||
success = default_network_rules_for_systemvm(conn, cmd.getVmName());
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.trace("Ignoring libvirt error.", e);
|
||||
|
|
@ -4686,7 +4746,7 @@ ServerResource {
|
|||
boolean success = false;
|
||||
Connect conn;
|
||||
try {
|
||||
conn = LibvirtConnection.getConnection();
|
||||
conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
||||
success = network_rules_vmSecondaryIp(conn, cmd.getVmName(), cmd.getVmSecIp(), cmd.getAction());
|
||||
} catch (LibvirtException e) {
|
||||
// TODO Auto-generated catch block
|
||||
|
|
|
|||
|
|
@ -16,33 +16,75 @@
|
|||
// under the License.
|
||||
package com.cloud.hypervisor.kvm.resource;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.libvirt.Connect;
|
||||
import org.libvirt.LibvirtException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class LibvirtConnection {
|
||||
private static final Logger s_logger = Logger
|
||||
.getLogger(LibvirtConnection.class);
|
||||
static private Map<String, Connect> _connections = new HashMap<String, Connect>();
|
||||
|
||||
static private Connect _connection;
|
||||
static private String _hypervisorURI;
|
||||
|
||||
static public Connect getConnection() throws LibvirtException {
|
||||
if (_connection == null) {
|
||||
_connection = new Connect(_hypervisorURI, false);
|
||||
return getConnection(_hypervisorURI);
|
||||
}
|
||||
|
||||
static public Connect getConnection(String hypervisorURI) throws LibvirtException {
|
||||
Connect conn = _connections.get(hypervisorURI);
|
||||
|
||||
if (conn == null) {
|
||||
conn = new Connect(hypervisorURI, false);
|
||||
_connections.put(hypervisorURI, conn);
|
||||
} else {
|
||||
try {
|
||||
_connection.getVersion();
|
||||
conn.getVersion();
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.debug("Connection with libvirtd is broken, due to "
|
||||
+ e.getMessage());
|
||||
_connection = new Connect(_hypervisorURI, false);
|
||||
conn = new Connect(hypervisorURI, false);
|
||||
_connections.put(hypervisorURI, conn);
|
||||
}
|
||||
}
|
||||
|
||||
return _connection;
|
||||
return conn;
|
||||
}
|
||||
|
||||
static public Connect getConnectionByVmName(String vmName) throws LibvirtException {
|
||||
HypervisorType[] hypervisors = new HypervisorType[] {HypervisorType.KVM, Hypervisor.HypervisorType.LXC};
|
||||
|
||||
for (HypervisorType hypervisor : hypervisors) {
|
||||
Connect conn = LibvirtConnection.getConnectionByType(hypervisor.toString());
|
||||
if (conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName.getBytes())) != null) {
|
||||
return conn;
|
||||
}
|
||||
}
|
||||
|
||||
// return the default connection
|
||||
return getConnection();
|
||||
}
|
||||
|
||||
static public Connect getConnectionByType(String hypervisorType) throws LibvirtException {
|
||||
return getConnection(getHypervisorURI(hypervisorType));
|
||||
}
|
||||
|
||||
static void initialize(String hypervisorURI) {
|
||||
_hypervisorURI = hypervisorURI;
|
||||
}
|
||||
|
||||
static String getHypervisorURI(String hypervisorType) {
|
||||
if ("LXC".equalsIgnoreCase(hypervisorType)) {
|
||||
return "lxc:///";
|
||||
} else {
|
||||
return "qemu:///system";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,17 +116,20 @@ public class LibvirtDomainXMLParser {
|
|||
|
||||
Element graphic = (Element) devices
|
||||
.getElementsByTagName("graphics").item(0);
|
||||
String port = graphic.getAttribute("port");
|
||||
if (port != null) {
|
||||
try {
|
||||
vncPort = Integer.parseInt(port);
|
||||
if (vncPort != -1) {
|
||||
vncPort = vncPort - 5900;
|
||||
} else {
|
||||
|
||||
if (graphic != null) {
|
||||
String port = graphic.getAttribute("port");
|
||||
if (port != null) {
|
||||
try {
|
||||
vncPort = Integer.parseInt(port);
|
||||
if (vncPort != -1) {
|
||||
vncPort = vncPort - 5900;
|
||||
} else {
|
||||
vncPort = null;
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
vncPort = null;
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
vncPort = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ package com.cloud.hypervisor.kvm.resource;
|
|||
|
||||
public class LibvirtStorageVolumeDef {
|
||||
public enum volFormat {
|
||||
RAW("raw"), QCOW2("qcow2"), DIR("dir");
|
||||
RAW("raw"), QCOW2("qcow2"), DIR("dir"), TAR("tar");
|
||||
private String _format;
|
||||
|
||||
volFormat(String format) {
|
||||
|
|
@ -38,6 +38,10 @@ public class LibvirtStorageVolumeDef {
|
|||
return RAW;
|
||||
} else if (format.equalsIgnoreCase("qcow2")) {
|
||||
return QCOW2;
|
||||
} else if (format.equalsIgnoreCase("dir")) {
|
||||
return DIR;
|
||||
} else if (format.equalsIgnoreCase("tar")) {
|
||||
return TAR;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ public class LibvirtVMDef {
|
|||
|
||||
public static class GuestDef {
|
||||
enum guestType {
|
||||
KVM, XEN, EXE
|
||||
KVM, XEN, EXE, LXC
|
||||
}
|
||||
|
||||
enum bootOrder {
|
||||
|
|
@ -62,6 +62,10 @@ public class LibvirtVMDef {
|
|||
_type = type;
|
||||
}
|
||||
|
||||
public guestType getGuestType() {
|
||||
return _type;
|
||||
}
|
||||
|
||||
public void setGuestArch(String arch) {
|
||||
_arch = arch;
|
||||
}
|
||||
|
|
@ -106,8 +110,16 @@ public class LibvirtVMDef {
|
|||
}
|
||||
guestDef.append("</os>\n");
|
||||
return guestDef.toString();
|
||||
} else
|
||||
} else if (_type == guestType.LXC) {
|
||||
StringBuilder guestDef = new StringBuilder();
|
||||
guestDef.append("<os>\n");
|
||||
guestDef.append("<type>exe</type>\n");
|
||||
guestDef.append("<init>/sbin/init</init>\n");
|
||||
guestDef.append("</os>\n");
|
||||
return guestDef.toString();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -279,6 +291,7 @@ public class LibvirtVMDef {
|
|||
|
||||
public static class DevicesDef {
|
||||
private String _emulator;
|
||||
private GuestDef.guestType _guestType;
|
||||
private final Map<String, List<?>> devices = new HashMap<String, List<?>>();
|
||||
|
||||
public boolean addDevice(Object device) {
|
||||
|
|
@ -298,6 +311,10 @@ public class LibvirtVMDef {
|
|||
_emulator = emulator;
|
||||
}
|
||||
|
||||
public void setGuestType(GuestDef.guestType guestType) {
|
||||
_guestType = guestType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder devicesBuilder = new StringBuilder();
|
||||
|
|
@ -309,6 +326,13 @@ public class LibvirtVMDef {
|
|||
|
||||
for (List<?> devs : devices.values()) {
|
||||
for (Object dev : devs) {
|
||||
if (_guestType == GuestDef.guestType.LXC) {
|
||||
if (dev instanceof GraphicDef ||
|
||||
dev instanceof InputDef ||
|
||||
dev instanceof DiskDef) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
devicesBuilder.append(dev.toString());
|
||||
}
|
||||
}
|
||||
|
|
@ -610,7 +634,7 @@ public class LibvirtVMDef {
|
|||
|
||||
public static class InterfaceDef {
|
||||
enum guestNetType {
|
||||
BRIDGE("bridge"), NETWORK("network"), USER("user"), ETHERNET(
|
||||
BRIDGE("bridge"), DIRECT("direct"), NETWORK("network"), USER("user"), ETHERNET(
|
||||
"ethernet"), INTERNAL("internal");
|
||||
String _type;
|
||||
|
||||
|
|
@ -648,6 +672,7 @@ public class LibvirtVMDef {
|
|||
* internal
|
||||
*/
|
||||
private hostNicType _hostNetType; /* Only used by agent java code */
|
||||
private String _netSourceMode;
|
||||
private String _sourceName;
|
||||
private String _networkName;
|
||||
private String _macAddr;
|
||||
|
|
@ -667,6 +692,16 @@ public class LibvirtVMDef {
|
|||
_model = model;
|
||||
}
|
||||
|
||||
public void defDirectNet(String sourceName, String targetName,
|
||||
String macAddr, nicModel model, String sourceMode) {
|
||||
_netType = guestNetType.DIRECT;
|
||||
_netSourceMode = sourceMode;
|
||||
_sourceName = sourceName;
|
||||
_networkName = targetName;
|
||||
_macAddr = macAddr;
|
||||
_model = model;
|
||||
}
|
||||
|
||||
public void defPrivateNet(String networkName, String targetName,
|
||||
String macAddr, nicModel model) {
|
||||
_netType = guestNetType.NETWORK;
|
||||
|
|
@ -699,6 +734,10 @@ public class LibvirtVMDef {
|
|||
return _netType;
|
||||
}
|
||||
|
||||
public String getNetSourceMode() {
|
||||
return _netSourceMode;
|
||||
}
|
||||
|
||||
public String getDevName() {
|
||||
return _networkName;
|
||||
}
|
||||
|
|
@ -739,6 +778,8 @@ public class LibvirtVMDef {
|
|||
netBuilder.append("<source bridge='" + _sourceName + "'/>\n");
|
||||
} else if (_netType == guestNetType.NETWORK) {
|
||||
netBuilder.append("<source network='" + _sourceName + "'/>\n");
|
||||
} else if (_netType == guestNetType.DIRECT) {
|
||||
netBuilder.append("<source dev='" + _sourceName + "' mode='" + _netSourceMode + "'/>\n");
|
||||
}
|
||||
if (_networkName != null) {
|
||||
netBuilder.append("<target dev='" + _networkName + "'/>\n");
|
||||
|
|
@ -934,10 +975,34 @@ public class LibvirtVMDef {
|
|||
}
|
||||
}
|
||||
|
||||
public static class FilesystemDef {
|
||||
private final String _sourcePath;
|
||||
private final String _targetPath;
|
||||
|
||||
public FilesystemDef(String sourcePath, String targetPath) {
|
||||
_sourcePath = sourcePath;
|
||||
_targetPath = targetPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder fsBuilder = new StringBuilder();
|
||||
fsBuilder.append("<filesystem type='mount'>\n");
|
||||
fsBuilder.append(" <source dir='" + _sourcePath + "'/>\n");
|
||||
fsBuilder.append(" <target dir='" + _targetPath + "'/>\n");
|
||||
fsBuilder.append("</filesystem>\n");
|
||||
return fsBuilder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public void setHvsType(String hvs) {
|
||||
_hvsType = hvs;
|
||||
}
|
||||
|
||||
public String getHvsType() {
|
||||
return _hvsType;
|
||||
}
|
||||
|
||||
public void setDomainName(String domainName) {
|
||||
_domName = domainName;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public class KVMPhysicalDisk {
|
|||
private KVMStoragePool pool;
|
||||
|
||||
public static enum PhysicalDiskFormat {
|
||||
RAW("raw"), QCOW2("qcow2");
|
||||
RAW("raw"), QCOW2("qcow2"), TAR("tar"), DIR("dir");
|
||||
String format;
|
||||
|
||||
private PhysicalDiskFormat(String format) {
|
||||
|
|
|
|||
|
|
@ -139,6 +139,10 @@ public class KVMStoragePoolManager {
|
|||
return adaptor.createDiskFromTemplate(template, name,
|
||||
KVMPhysicalDisk.PhysicalDiskFormat.RAW, template.getSize(),
|
||||
destPool);
|
||||
} else if (template.getFormat() == KVMPhysicalDisk.PhysicalDiskFormat.DIR) {
|
||||
return adaptor.createDiskFromTemplate(template, name,
|
||||
KVMPhysicalDisk.PhysicalDiskFormat.DIR,
|
||||
template.getSize(), destPool);
|
||||
} else {
|
||||
return adaptor.createDiskFromTemplate(template, name,
|
||||
KVMPhysicalDisk.PhysicalDiskFormat.QCOW2,
|
||||
|
|
|
|||
|
|
@ -390,7 +390,14 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
disk.setSize(vol.getInfo().allocation);
|
||||
disk.setVirtualSize(vol.getInfo().capacity);
|
||||
if (voldef.getFormat() == null) {
|
||||
disk.setFormat(pool.getDefaultFormat());
|
||||
File diskDir = new File(disk.getPath());
|
||||
if (diskDir.exists() && diskDir.isDirectory()) {
|
||||
disk.setFormat(PhysicalDiskFormat.DIR);
|
||||
} else if (volumeUuid.endsWith("tar") || volumeUuid.endsWith(("TAR"))) {
|
||||
disk.setFormat(PhysicalDiskFormat.TAR);
|
||||
} else {
|
||||
disk.setFormat(pool.getDefaultFormat());
|
||||
}
|
||||
} else if (pool.getType() == StoragePoolType.RBD) {
|
||||
disk.setFormat(KVMPhysicalDisk.PhysicalDiskFormat.RAW);
|
||||
} else if (voldef.getFormat() == LibvirtStorageVolumeDef.volFormat.QCOW2) {
|
||||
|
|
@ -590,6 +597,10 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
libvirtformat = LibvirtStorageVolumeDef.volFormat.QCOW2;
|
||||
} else if (format == PhysicalDiskFormat.RAW) {
|
||||
libvirtformat = LibvirtStorageVolumeDef.volFormat.RAW;
|
||||
} else if (format == PhysicalDiskFormat.DIR) {
|
||||
libvirtformat = LibvirtStorageVolumeDef.volFormat.DIR;
|
||||
} else if (format == PhysicalDiskFormat.TAR) {
|
||||
libvirtformat = LibvirtStorageVolumeDef.volFormat.TAR;
|
||||
}
|
||||
|
||||
LibvirtStorageVolumeDef volDef = new LibvirtStorageVolumeDef(name,
|
||||
|
|
@ -640,7 +651,13 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
if (destPool.getType() != StoragePoolType.RBD) {
|
||||
disk = destPool.createPhysicalDisk(newUuid, format, template.getVirtualSize());
|
||||
|
||||
if (format == PhysicalDiskFormat.QCOW2) {
|
||||
if (template.getFormat() == PhysicalDiskFormat.TAR) {
|
||||
Script.runSimpleBashScript("tar -x -f " + template.getPath() + " -C " + disk.getPath());
|
||||
} else if (template.getFormat() == PhysicalDiskFormat.DIR) {
|
||||
Script.runSimpleBashScript("mkdir -p " + disk.getPath());
|
||||
Script.runSimpleBashScript("chmod 755 " + disk.getPath());
|
||||
Script.runSimpleBashScript("cp -p -r " + template.getPath() + "/* " + disk.getPath());
|
||||
} else if (format == PhysicalDiskFormat.QCOW2) {
|
||||
Script.runSimpleBashScript("qemu-img create -f "
|
||||
+ template.getFormat() + " -b " + template.getPath() + " "
|
||||
+ disk.getPath());
|
||||
|
|
@ -724,7 +741,11 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
|
||||
KVMPhysicalDisk newDisk;
|
||||
if (destPool.getType() != StoragePoolType.RBD) {
|
||||
newDisk = destPool.createPhysicalDisk(name, disk.getVirtualSize());
|
||||
if (disk.getFormat() == PhysicalDiskFormat.TAR) {
|
||||
newDisk = destPool.createPhysicalDisk(name, PhysicalDiskFormat.DIR, disk.getVirtualSize());
|
||||
} else {
|
||||
newDisk = destPool.createPhysicalDisk(name, disk.getVirtualSize());
|
||||
}
|
||||
} else {
|
||||
newDisk = new KVMPhysicalDisk(destPool.getSourceDir() + "/" + name, name, destPool);
|
||||
newDisk.setFormat(PhysicalDiskFormat.RAW);
|
||||
|
|
@ -739,7 +760,15 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
|
|||
PhysicalDiskFormat destFormat = newDisk.getFormat();
|
||||
|
||||
if ((srcPool.getType() != StoragePoolType.RBD) && (destPool.getType() != StoragePoolType.RBD)) {
|
||||
if (sourceFormat.equals(destFormat) &&
|
||||
if (sourceFormat == PhysicalDiskFormat.TAR) {
|
||||
Script.runSimpleBashScript("tar -x -f " + sourcePath + " -C " + destPath);
|
||||
|
||||
} else if (sourceFormat == PhysicalDiskFormat.DIR) {
|
||||
Script.runSimpleBashScript("mkdir -p " + destPath);
|
||||
Script.runSimpleBashScript("chmod 755 " + destPath);
|
||||
Script.runSimpleBashScript("cp -p -r " + sourcePath + "/* " + destPath);
|
||||
|
||||
} else if (sourceFormat.equals(destFormat) &&
|
||||
Script.runSimpleBashScript("qemu-img info " + sourcePath + "|grep backing") == null) {
|
||||
Script.runSimpleBashScript("cp -f " + sourcePath + " " + destPath);
|
||||
|
||||
|
|
|
|||
|
|
@ -35,4 +35,18 @@ public class LibvirtVMDefTest extends TestCase {
|
|||
|
||||
assertEquals(expected, ifDef.toString());
|
||||
}
|
||||
|
||||
public void testInterfaceDirectNet() {
|
||||
LibvirtVMDef.InterfaceDef ifDef = new LibvirtVMDef.InterfaceDef();
|
||||
ifDef.defDirectNet("targetDeviceName", null, "00:11:22:aa:bb:dd", LibvirtVMDef.InterfaceDef.nicModel.VIRTIO, "private");
|
||||
|
||||
String expected = "<interface type='" + LibvirtVMDef.InterfaceDef.guestNetType.DIRECT + "'>\n" +
|
||||
"<source dev='targetDeviceName' mode='private'/>\n" +
|
||||
"<mac address='00:11:22:aa:bb:dd'/>\n" +
|
||||
"<model type='virtio'/>\n" +
|
||||
"</interface>\n";
|
||||
|
||||
assertEquals(expected, ifDef.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,6 +157,10 @@ then
|
|||
then
|
||||
ext="ova"
|
||||
templateId=(`mysql -h $dbHost --user=$dbUser --password=$dbPassword --skip-column-names -U cloud -e "select max(id) from cloud.vm_template where type = \"SYSTEM\" and hypervisor_type = \"VMware\" and removed is null"`)
|
||||
elif [ "$hyper" == "lxc" ]
|
||||
then
|
||||
ext="qcow2"
|
||||
templateId=(`mysql -h $dbHost --user=$dbUser --password=$dbPassword --skip-column-names -U cloud -e "select max(id) from cloud.vm_template where type = \"SYSTEM\" and hypervisor_type = \"LXC\" and removed is null"`)
|
||||
else
|
||||
usage
|
||||
failed 2
|
||||
|
|
|
|||
|
|
@ -1194,11 +1194,13 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
|
|||
}
|
||||
} else {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
if (secondaryStorageHost != null) {
|
||||
s_logger.debug("Zone host is ready, but console proxy template: " + template.getId() + " is not ready on secondary storage: " + secondaryStorageHost.getId());
|
||||
} else {
|
||||
s_logger.debug("Zone host is ready, but console proxy template: " + template.getId() + " is not ready on secondary storage.");
|
||||
}
|
||||
if (template == null) {
|
||||
s_logger.debug("Zone host is ready, but console proxy template is null");
|
||||
} else if (secondaryStorageHost != null) {
|
||||
s_logger.debug("Zone host is ready, but console proxy template: " + template.getId() + " is not ready on secondary storage: " + secondaryStorageHost.getId());
|
||||
} else {
|
||||
s_logger.debug("Zone host is ready, but console proxy template: " + template.getId() + " is not ready on secondary storage.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package com.cloud.hypervisor;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
|
||||
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.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
|
||||
@Local(value=HypervisorGuru.class)
|
||||
public class LXCGuru extends HypervisorGuruBase implements HypervisorGuru {
|
||||
@Inject GuestOSDao _guestOsDao;
|
||||
|
||||
@Override
|
||||
public HypervisorType getHypervisorType() {
|
||||
return HypervisorType.LXC;
|
||||
}
|
||||
|
||||
protected LXCGuru() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends VirtualMachine> VirtualMachineTO implement(
|
||||
VirtualMachineProfile<T> vm) {
|
||||
VirtualMachineTO to = toVirtualMachineTO(vm);
|
||||
|
||||
// Determine the VM's OS description
|
||||
GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId());
|
||||
to.setOs(guestOS.getDisplayName());
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trackVmHostChange() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -16,380 +16,21 @@
|
|||
// under the License.
|
||||
package com.cloud.hypervisor.kvm.discoverer;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.resource.Discoverer;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.AgentManager;
|
||||
import com.cloud.agent.Listener;
|
||||
import com.cloud.agent.api.AgentControlAnswer;
|
||||
import com.cloud.agent.api.AgentControlCommand;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.ShutdownCommand;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.StartupRoutingCommand;
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.dao.ClusterDao;
|
||||
import com.cloud.exception.AgentUnavailableException;
|
||||
import com.cloud.exception.DiscoveredWithErrorException;
|
||||
import com.cloud.exception.DiscoveryException;
|
||||
import com.cloud.exception.OperationTimedoutException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.Status;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.network.NetworkModel;
|
||||
import com.cloud.network.PhysicalNetworkSetupInfo;
|
||||
import com.cloud.resource.Discoverer;
|
||||
import com.cloud.resource.DiscovererBase;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.resource.ResourceStateAdapter;
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.resource.UnableDeleteHostException;
|
||||
import com.cloud.utils.ssh.SSHCmdHelper;
|
||||
import javax.ejb.Local;
|
||||
|
||||
@Local(value=Discoverer.class)
|
||||
public class KvmServerDiscoverer extends DiscovererBase implements Discoverer,
|
||||
Listener, ResourceStateAdapter {
|
||||
public class KvmServerDiscoverer extends LibvirtServerDiscoverer {
|
||||
private static final Logger s_logger = Logger.getLogger(KvmServerDiscoverer.class);
|
||||
private String _hostIp;
|
||||
private final int _waitTime = 5; /*wait for 5 minutes*/
|
||||
private String _kvmPrivateNic;
|
||||
private String _kvmPublicNic;
|
||||
private String _kvmGuestNic;
|
||||
@Inject HostDao _hostDao = null;
|
||||
@Inject ClusterDao _clusterDao;
|
||||
@Inject ResourceManager _resourceMgr;
|
||||
@Inject AgentManager _agentMgr;
|
||||
@Inject ConfigurationDao _configDao;
|
||||
@Inject NetworkModel _networkMgr;
|
||||
|
||||
@Override
|
||||
public boolean processAnswers(long agentId, long seq, Answer[] answers) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processCommands(long agentId, long seq, Command[] commands) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentControlAnswer processControlCommand(long agentId,
|
||||
AgentControlCommand cmd) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processDisconnect(long agentId, Status state) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRecurring() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimeout() {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processTimeout(long agentId, long seq) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<? extends ServerResource, Map<String, String>> find(long dcId,
|
||||
Long podId, Long clusterId, URI uri, String username,
|
||||
String password, List<String> hostTags) throws DiscoveryException {
|
||||
|
||||
ClusterVO cluster = _clusterDao.findById(clusterId);
|
||||
if(cluster == null || cluster.getHypervisorType() != HypervisorType.KVM) {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("invalid cluster id or cluster is not for KVM hypervisors");
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<KvmDummyResourceBase, Map<String, String>> resources = new HashMap<KvmDummyResourceBase, Map<String, String>>();
|
||||
Map<String, String> details = new HashMap<String, String>();
|
||||
if (!uri.getScheme().equals("http")) {
|
||||
String msg = "urlString is not http so we're not taking care of the discovery for this: " + uri;
|
||||
s_logger.debug(msg);
|
||||
return null;
|
||||
}
|
||||
com.trilead.ssh2.Connection sshConnection = null;
|
||||
String agentIp = null;
|
||||
try {
|
||||
|
||||
String hostname = uri.getHost();
|
||||
InetAddress ia = InetAddress.getByName(hostname);
|
||||
agentIp = ia.getHostAddress();
|
||||
String guid = UUID.nameUUIDFromBytes(agentIp.getBytes()).toString();
|
||||
String guidWithTail = guid + "-LibvirtComputingResource";/*tail added by agent.java*/
|
||||
if (_resourceMgr.findHostByGuid(guidWithTail) != null) {
|
||||
s_logger.debug("Skipping " + agentIp + " because " + guidWithTail + " is already in the database.");
|
||||
return null;
|
||||
}
|
||||
|
||||
sshConnection = new com.trilead.ssh2.Connection(agentIp, 22);
|
||||
|
||||
sshConnection.connect(null, 60000, 60000);
|
||||
if (!sshConnection.authenticateWithPassword(username, password)) {
|
||||
s_logger.debug("Failed to authenticate");
|
||||
throw new DiscoveredWithErrorException("Authentication error");
|
||||
}
|
||||
|
||||
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, "lsmod|grep kvm", 3)) {
|
||||
s_logger.debug("It's not a KVM enabled machine");
|
||||
return null;
|
||||
}
|
||||
|
||||
List <PhysicalNetworkSetupInfo> netInfos = _networkMgr.getPhysicalNetworkInfo(dcId, HypervisorType.KVM);
|
||||
String kvmPrivateNic = null;
|
||||
String kvmPublicNic = null;
|
||||
String kvmGuestNic = null;
|
||||
|
||||
for (PhysicalNetworkSetupInfo info : netInfos) {
|
||||
if (info.getPrivateNetworkName() != null) {
|
||||
kvmPrivateNic = info.getPrivateNetworkName();
|
||||
}
|
||||
if (info.getPublicNetworkName() != null) {
|
||||
kvmPublicNic = info.getPublicNetworkName();
|
||||
}
|
||||
if (info.getGuestNetworkName() != null) {
|
||||
kvmGuestNic = info.getGuestNetworkName();
|
||||
}
|
||||
}
|
||||
|
||||
if (kvmPrivateNic == null && kvmPublicNic == null && kvmGuestNic == null) {
|
||||
kvmPrivateNic = _kvmPrivateNic;
|
||||
kvmPublicNic = _kvmPublicNic;
|
||||
kvmGuestNic = _kvmGuestNic;
|
||||
}
|
||||
|
||||
if (kvmPublicNic == null) {
|
||||
kvmPublicNic = (kvmGuestNic != null) ? kvmGuestNic : kvmPrivateNic;
|
||||
}
|
||||
|
||||
if (kvmPrivateNic == null) {
|
||||
kvmPrivateNic = (kvmPublicNic != null) ? kvmPublicNic : kvmGuestNic;
|
||||
}
|
||||
|
||||
if (kvmGuestNic == null) {
|
||||
kvmGuestNic = (kvmPublicNic != null) ? kvmPublicNic : kvmPrivateNic;
|
||||
}
|
||||
|
||||
String parameters = " -m " + _hostIp + " -z " + dcId + " -p " + podId + " -c " + clusterId + " -g " + guid + " -a";
|
||||
|
||||
parameters += " --pubNic=" + kvmPublicNic;
|
||||
parameters += " --prvNic=" + kvmPrivateNic;
|
||||
parameters += " --guestNic=" + kvmGuestNic;
|
||||
|
||||
SSHCmdHelper.sshExecuteCmd(sshConnection, "cloudstack-setup-agent " + parameters, 3);
|
||||
|
||||
KvmDummyResourceBase kvmResource = new KvmDummyResourceBase();
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
|
||||
params.put("zone", Long.toString(dcId));
|
||||
params.put("pod", Long.toString(podId));
|
||||
params.put("cluster", Long.toString(clusterId));
|
||||
params.put("guid", guid);
|
||||
params.put("agentIp", agentIp);
|
||||
kvmResource.configure("kvm agent", params);
|
||||
resources.put(kvmResource, details);
|
||||
|
||||
HostVO connectedHost = waitForHostConnect(dcId, podId, clusterId, guidWithTail);
|
||||
if (connectedHost == null)
|
||||
return null;
|
||||
|
||||
details.put("guid", guidWithTail);
|
||||
|
||||
// place a place holder guid derived from cluster ID
|
||||
if (cluster.getGuid() == null) {
|
||||
cluster.setGuid(UUID.nameUUIDFromBytes(String.valueOf(clusterId).getBytes()).toString());
|
||||
_clusterDao.update(clusterId, cluster);
|
||||
}
|
||||
|
||||
//save user name and password
|
||||
_hostDao.loadDetails(connectedHost);
|
||||
Map<String, String> hostDetails = connectedHost.getDetails();
|
||||
hostDetails.put("password", password);
|
||||
hostDetails.put("username", username);
|
||||
_hostDao.saveDetails(connectedHost);
|
||||
return resources;
|
||||
} catch (DiscoveredWithErrorException e){
|
||||
throw e;
|
||||
}catch (Exception e) {
|
||||
String msg = " can't setup agent, due to " + e.toString() + " - " + e.getMessage();
|
||||
s_logger.warn(msg);
|
||||
} finally {
|
||||
if (sshConnection != null)
|
||||
sshConnection.close();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private HostVO waitForHostConnect(long dcId, long podId, long clusterId, String guid) {
|
||||
for (int i = 0; i < _waitTime *2; i++) {
|
||||
List<HostVO> hosts = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, clusterId, podId, dcId);
|
||||
for (HostVO host : hosts) {
|
||||
if (host.getGuid().equalsIgnoreCase(guid)) {
|
||||
return host;
|
||||
}
|
||||
}
|
||||
try {
|
||||
Thread.sleep(30000);
|
||||
} catch (InterruptedException e) {
|
||||
s_logger.debug("Failed to sleep: " + e.toString());
|
||||
}
|
||||
}
|
||||
s_logger.debug("Timeout, to wait for the host connecting to mgt svr, assuming it is failed");
|
||||
List<HostVO> hosts = _resourceMgr.findHostByGuid(dcId, guid);
|
||||
if (hosts.size() == 1) {
|
||||
return hosts.get(0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
// _setupAgentPath = Script.findScript(getPatchPath(), "setup_agent.sh");
|
||||
_kvmPrivateNic = _configDao.getValue(Config.KvmPrivateNetwork.key());
|
||||
if (_kvmPrivateNic == null) {
|
||||
_kvmPrivateNic = "cloudbr0";
|
||||
}
|
||||
|
||||
_kvmPublicNic = _configDao.getValue(Config.KvmPublicNetwork.key());
|
||||
if (_kvmPublicNic == null) {
|
||||
_kvmPublicNic = _kvmPrivateNic;
|
||||
}
|
||||
|
||||
_kvmGuestNic = _configDao.getValue(Config.KvmGuestNetwork.key());
|
||||
if (_kvmGuestNic == null) {
|
||||
_kvmGuestNic = _kvmPrivateNic;
|
||||
}
|
||||
|
||||
_hostIp = _configDao.getValue("host");
|
||||
if (_hostIp == null) {
|
||||
throw new ConfigurationException("Can't get host IP");
|
||||
}
|
||||
_resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
|
||||
return true;
|
||||
public Hypervisor.HypervisorType getHypervisorType() {
|
||||
return Hypervisor.HypervisorType.KVM;
|
||||
}
|
||||
|
||||
protected String getPatchPath() {
|
||||
return "scripts/vm/hypervisor/kvm/";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDiscovery(List<HostVO> hosts, long msId)
|
||||
throws DiscoveryException {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public Hypervisor.HypervisorType getHypervisorType() {
|
||||
return Hypervisor.HypervisorType.KVM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchHypervisor(String hypervisor) {
|
||||
// for backwards compatibility, if not supplied, always let to try it
|
||||
if(hypervisor == null)
|
||||
return true;
|
||||
|
||||
return Hypervisor.HypervisorType.KVM.toString().equalsIgnoreCase(hypervisor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
|
||||
StartupCommand firstCmd = cmd[0];
|
||||
if (!(firstCmd instanceof StartupRoutingCommand)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
StartupRoutingCommand ssCmd = ((StartupRoutingCommand) firstCmd);
|
||||
if (ssCmd.getHypervisorType() != HypervisorType.KVM) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* KVM requires host are the same in cluster */
|
||||
ClusterVO clusterVO = _clusterDao.findById(host.getClusterId());
|
||||
List<HostVO> hostsInCluster = _resourceMgr.listAllHostsInCluster(clusterVO.getId());
|
||||
if (!hostsInCluster.isEmpty()) {
|
||||
HostVO oneHost = hostsInCluster.get(0);
|
||||
_hostDao.loadDetails(oneHost);
|
||||
String hostOsInCluster = oneHost.getDetail("Host.OS");
|
||||
String hostOs = ssCmd.getHostDetails().get("Host.OS");
|
||||
if (!hostOsInCluster.equalsIgnoreCase(hostOs)) {
|
||||
throw new IllegalArgumentException("Can't add host: " + firstCmd.getPrivateIpAddress() + " with hostOS: " + hostOs + " into a cluster,"
|
||||
+ "in which there are " + hostOsInCluster + " hosts added");
|
||||
}
|
||||
}
|
||||
|
||||
_hostDao.loadDetails(host);
|
||||
|
||||
return _resourceMgr.fillRoutingHostVO(host, ssCmd, HypervisorType.KVM, host.getDetails(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details,
|
||||
List<String> hostTags) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
|
||||
if (host.getType() != Host.Type.Routing || host.getHypervisorType() != HypervisorType.KVM) {
|
||||
return null;
|
||||
}
|
||||
|
||||
_resourceMgr.deleteRoutingHost(host, isForced, isForceDeleteStorage);
|
||||
try {
|
||||
ShutdownCommand cmd = new ShutdownCommand(ShutdownCommand.DeleteHost, null);
|
||||
_agentMgr.send(host.getId(), cmd);
|
||||
} catch (AgentUnavailableException e) {
|
||||
s_logger.warn("Sending ShutdownCommand failed: ", e);
|
||||
} catch (OperationTimedoutException e) {
|
||||
s_logger.warn("Sending ShutdownCommand failed: ", e);
|
||||
}
|
||||
|
||||
return new DeleteHostAnswer(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
_resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName());
|
||||
return super.stop();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,393 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package com.cloud.hypervisor.kvm.discoverer;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.AgentManager;
|
||||
import com.cloud.agent.Listener;
|
||||
import com.cloud.agent.api.AgentControlAnswer;
|
||||
import com.cloud.agent.api.AgentControlCommand;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.ShutdownCommand;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.StartupRoutingCommand;
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.dc.ClusterVO;
|
||||
import com.cloud.dc.dao.ClusterDao;
|
||||
import com.cloud.exception.AgentUnavailableException;
|
||||
import com.cloud.exception.DiscoveredWithErrorException;
|
||||
import com.cloud.exception.DiscoveryException;
|
||||
import com.cloud.exception.OperationTimedoutException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.Status;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.network.NetworkModel;
|
||||
import com.cloud.network.PhysicalNetworkSetupInfo;
|
||||
import com.cloud.resource.Discoverer;
|
||||
import com.cloud.resource.DiscovererBase;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.resource.ResourceStateAdapter;
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.resource.UnableDeleteHostException;
|
||||
import com.cloud.utils.ssh.SSHCmdHelper;
|
||||
|
||||
public abstract class LibvirtServerDiscoverer extends DiscovererBase implements Discoverer,
|
||||
Listener, ResourceStateAdapter {
|
||||
private static final Logger s_logger = Logger.getLogger(LibvirtServerDiscoverer.class);
|
||||
private String _hostIp;
|
||||
private final int _waitTime = 5; /*wait for 5 minutes*/
|
||||
private String _kvmPrivateNic;
|
||||
private String _kvmPublicNic;
|
||||
private String _kvmGuestNic;
|
||||
@Inject HostDao _hostDao = null;
|
||||
@Inject ClusterDao _clusterDao;
|
||||
@Inject ResourceManager _resourceMgr;
|
||||
@Inject AgentManager _agentMgr;
|
||||
@Inject ConfigurationDao _configDao;
|
||||
@Inject NetworkModel _networkMgr;
|
||||
|
||||
public abstract Hypervisor.HypervisorType getHypervisorType();
|
||||
|
||||
@Override
|
||||
public boolean processAnswers(long agentId, long seq, Answer[] answers) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processCommands(long agentId, long seq, Command[] commands) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgentControlAnswer processControlCommand(long agentId,
|
||||
AgentControlCommand cmd) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processDisconnect(long agentId, Status state) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRecurring() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTimeout() {
|
||||
// TODO Auto-generated method stub
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processTimeout(long agentId, long seq) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<? extends ServerResource, Map<String, String>> find(long dcId,
|
||||
Long podId, Long clusterId, URI uri, String username,
|
||||
String password, List<String> hostTags) throws DiscoveryException {
|
||||
|
||||
ClusterVO cluster = _clusterDao.findById(clusterId);
|
||||
if(cluster == null || cluster.getHypervisorType() != getHypervisorType()) {
|
||||
if(s_logger.isInfoEnabled())
|
||||
s_logger.info("invalid cluster id or cluster is not for " + getHypervisorType() + " hypervisors");
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<KvmDummyResourceBase, Map<String, String>> resources = new HashMap<KvmDummyResourceBase, Map<String, String>>();
|
||||
Map<String, String> details = new HashMap<String, String>();
|
||||
if (!uri.getScheme().equals("http")) {
|
||||
String msg = "urlString is not http so we're not taking care of the discovery for this: " + uri;
|
||||
s_logger.debug(msg);
|
||||
return null;
|
||||
}
|
||||
com.trilead.ssh2.Connection sshConnection = null;
|
||||
String agentIp = null;
|
||||
try {
|
||||
|
||||
String hostname = uri.getHost();
|
||||
InetAddress ia = InetAddress.getByName(hostname);
|
||||
agentIp = ia.getHostAddress();
|
||||
String guid = UUID.nameUUIDFromBytes(agentIp.getBytes()).toString();
|
||||
String guidWithTail = guid + "-LibvirtComputingResource";/*tail added by agent.java*/
|
||||
if (_resourceMgr.findHostByGuid(guidWithTail) != null) {
|
||||
s_logger.debug("Skipping " + agentIp + " because " + guidWithTail + " is already in the database.");
|
||||
return null;
|
||||
}
|
||||
|
||||
sshConnection = new com.trilead.ssh2.Connection(agentIp, 22);
|
||||
|
||||
sshConnection.connect(null, 60000, 60000);
|
||||
if (!sshConnection.authenticateWithPassword(username, password)) {
|
||||
s_logger.debug("Failed to authenticate");
|
||||
throw new DiscoveredWithErrorException("Authentication error");
|
||||
}
|
||||
|
||||
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, "lsmod|grep kvm", 3)) {
|
||||
s_logger.debug("It's not a KVM enabled machine");
|
||||
return null;
|
||||
}
|
||||
|
||||
List <PhysicalNetworkSetupInfo> netInfos = _networkMgr.getPhysicalNetworkInfo(dcId, getHypervisorType());
|
||||
String kvmPrivateNic = null;
|
||||
String kvmPublicNic = null;
|
||||
String kvmGuestNic = null;
|
||||
|
||||
for (PhysicalNetworkSetupInfo info : netInfos) {
|
||||
if (info.getPrivateNetworkName() != null) {
|
||||
kvmPrivateNic = info.getPrivateNetworkName();
|
||||
}
|
||||
if (info.getPublicNetworkName() != null) {
|
||||
kvmPublicNic = info.getPublicNetworkName();
|
||||
}
|
||||
if (info.getGuestNetworkName() != null) {
|
||||
kvmGuestNic = info.getGuestNetworkName();
|
||||
}
|
||||
}
|
||||
|
||||
if (kvmPrivateNic == null && kvmPublicNic == null && kvmGuestNic == null) {
|
||||
kvmPrivateNic = _kvmPrivateNic;
|
||||
kvmPublicNic = _kvmPublicNic;
|
||||
kvmGuestNic = _kvmGuestNic;
|
||||
}
|
||||
|
||||
if (kvmPublicNic == null) {
|
||||
kvmPublicNic = (kvmGuestNic != null) ? kvmGuestNic : kvmPrivateNic;
|
||||
}
|
||||
|
||||
if (kvmPrivateNic == null) {
|
||||
kvmPrivateNic = (kvmPublicNic != null) ? kvmPublicNic : kvmGuestNic;
|
||||
}
|
||||
|
||||
if (kvmGuestNic == null) {
|
||||
kvmGuestNic = (kvmPublicNic != null) ? kvmPublicNic : kvmPrivateNic;
|
||||
}
|
||||
|
||||
String parameters = " -m " + _hostIp + " -z " + dcId + " -p " + podId + " -c " + clusterId + " -g " + guid + " -a";
|
||||
|
||||
parameters += " --pubNic=" + kvmPublicNic;
|
||||
parameters += " --prvNic=" + kvmPrivateNic;
|
||||
parameters += " --guestNic=" + kvmGuestNic;
|
||||
|
||||
SSHCmdHelper.sshExecuteCmd(sshConnection, "cloudstack-setup-agent " + parameters, 3);
|
||||
|
||||
KvmDummyResourceBase kvmResource = new KvmDummyResourceBase();
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
|
||||
params.put("zone", Long.toString(dcId));
|
||||
params.put("pod", Long.toString(podId));
|
||||
params.put("cluster", Long.toString(clusterId));
|
||||
params.put("guid", guid);
|
||||
params.put("agentIp", agentIp);
|
||||
kvmResource.configure("kvm agent", params);
|
||||
resources.put(kvmResource, details);
|
||||
|
||||
HostVO connectedHost = waitForHostConnect(dcId, podId, clusterId, guidWithTail);
|
||||
if (connectedHost == null)
|
||||
return null;
|
||||
|
||||
details.put("guid", guidWithTail);
|
||||
|
||||
// place a place holder guid derived from cluster ID
|
||||
if (cluster.getGuid() == null) {
|
||||
cluster.setGuid(UUID.nameUUIDFromBytes(String.valueOf(clusterId).getBytes()).toString());
|
||||
_clusterDao.update(clusterId, cluster);
|
||||
}
|
||||
|
||||
//save user name and password
|
||||
_hostDao.loadDetails(connectedHost);
|
||||
Map<String, String> hostDetails = connectedHost.getDetails();
|
||||
hostDetails.put("password", password);
|
||||
hostDetails.put("username", username);
|
||||
_hostDao.saveDetails(connectedHost);
|
||||
return resources;
|
||||
} catch (DiscoveredWithErrorException e){
|
||||
throw e;
|
||||
}catch (Exception e) {
|
||||
String msg = " can't setup agent, due to " + e.toString() + " - " + e.getMessage();
|
||||
s_logger.warn(msg);
|
||||
} finally {
|
||||
if (sshConnection != null)
|
||||
sshConnection.close();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private HostVO waitForHostConnect(long dcId, long podId, long clusterId, String guid) {
|
||||
for (int i = 0; i < _waitTime *2; i++) {
|
||||
List<HostVO> hosts = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, clusterId, podId, dcId);
|
||||
for (HostVO host : hosts) {
|
||||
if (host.getGuid().equalsIgnoreCase(guid)) {
|
||||
return host;
|
||||
}
|
||||
}
|
||||
try {
|
||||
Thread.sleep(30000);
|
||||
} catch (InterruptedException e) {
|
||||
s_logger.debug("Failed to sleep: " + e.toString());
|
||||
}
|
||||
}
|
||||
s_logger.debug("Timeout, to wait for the host connecting to mgt svr, assuming it is failed");
|
||||
List<HostVO> hosts = _resourceMgr.findHostByGuid(dcId, guid);
|
||||
if (hosts.size() == 1) {
|
||||
return hosts.get(0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
// _setupAgentPath = Script.findScript(getPatchPath(), "setup_agent.sh");
|
||||
_kvmPrivateNic = _configDao.getValue(Config.KvmPrivateNetwork.key());
|
||||
if (_kvmPrivateNic == null) {
|
||||
_kvmPrivateNic = "cloudbr0";
|
||||
}
|
||||
|
||||
_kvmPublicNic = _configDao.getValue(Config.KvmPublicNetwork.key());
|
||||
if (_kvmPublicNic == null) {
|
||||
_kvmPublicNic = _kvmPrivateNic;
|
||||
}
|
||||
|
||||
_kvmGuestNic = _configDao.getValue(Config.KvmGuestNetwork.key());
|
||||
if (_kvmGuestNic == null) {
|
||||
_kvmGuestNic = _kvmPrivateNic;
|
||||
}
|
||||
|
||||
_hostIp = _configDao.getValue("host");
|
||||
if (_hostIp == null) {
|
||||
throw new ConfigurationException("Can't get host IP");
|
||||
}
|
||||
_resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected String getPatchPath() {
|
||||
return "scripts/vm/hypervisor/kvm/";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postDiscovery(List<HostVO> hosts, long msId)
|
||||
throws DiscoveryException {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchHypervisor(String hypervisor) {
|
||||
// for backwards compatibility, if not supplied, always let to try it
|
||||
if(hypervisor == null)
|
||||
return true;
|
||||
|
||||
return getHypervisorType().toString().equalsIgnoreCase(hypervisor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
|
||||
StartupCommand firstCmd = cmd[0];
|
||||
if (!(firstCmd instanceof StartupRoutingCommand)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
StartupRoutingCommand ssCmd = ((StartupRoutingCommand) firstCmd);
|
||||
if (ssCmd.getHypervisorType() != getHypervisorType()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* KVM requires host are the same in cluster */
|
||||
ClusterVO clusterVO = _clusterDao.findById(host.getClusterId());
|
||||
List<HostVO> hostsInCluster = _resourceMgr.listAllHostsInCluster(clusterVO.getId());
|
||||
if (!hostsInCluster.isEmpty()) {
|
||||
HostVO oneHost = hostsInCluster.get(0);
|
||||
_hostDao.loadDetails(oneHost);
|
||||
String hostOsInCluster = oneHost.getDetail("Host.OS");
|
||||
String hostOs = ssCmd.getHostDetails().get("Host.OS");
|
||||
if (!hostOsInCluster.equalsIgnoreCase(hostOs)) {
|
||||
throw new IllegalArgumentException("Can't add host: " + firstCmd.getPrivateIpAddress() + " with hostOS: " + hostOs + " into a cluster,"
|
||||
+ "in which there are " + hostOsInCluster + " hosts added");
|
||||
}
|
||||
}
|
||||
|
||||
_hostDao.loadDetails(host);
|
||||
|
||||
return _resourceMgr.fillRoutingHostVO(host, ssCmd, getHypervisorType(), host.getDetails(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details,
|
||||
List<String> hostTags) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
|
||||
if (host.getType() != Host.Type.Routing ||
|
||||
(host.getHypervisorType() != HypervisorType.KVM &&
|
||||
host.getHypervisorType() != HypervisorType.LXC)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
_resourceMgr.deleteRoutingHost(host, isForced, isForceDeleteStorage);
|
||||
try {
|
||||
ShutdownCommand cmd = new ShutdownCommand(ShutdownCommand.DeleteHost, null);
|
||||
_agentMgr.send(host.getId(), cmd);
|
||||
} catch (AgentUnavailableException e) {
|
||||
s_logger.warn("Sending ShutdownCommand failed: ", e);
|
||||
} catch (OperationTimedoutException e) {
|
||||
s_logger.warn("Sending ShutdownCommand failed: ", e);
|
||||
}
|
||||
|
||||
return new DeleteHostAnswer(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
_resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName());
|
||||
return super.stop();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package com.cloud.hypervisor.kvm.discoverer;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.resource.Discoverer;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import javax.ejb.Local;
|
||||
|
||||
@Local(value=Discoverer.class)
|
||||
public class LxcServerDiscoverer extends LibvirtServerDiscoverer {
|
||||
private static final Logger s_logger = Logger.getLogger(LxcServerDiscoverer.class);
|
||||
|
||||
public Hypervisor.HypervisorType getHypervisorType() {
|
||||
return Hypervisor.HypervisorType.LXC;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -72,7 +72,8 @@ public class SshKeysDistriMonitor implements Listener {
|
|||
public void processConnect(HostVO host, StartupCommand cmd, boolean forRebalance) throws ConnectionException {
|
||||
if (cmd instanceof StartupRoutingCommand) {
|
||||
if (((StartupRoutingCommand) cmd).getHypervisorType() == HypervisorType.KVM ||
|
||||
((StartupRoutingCommand) cmd).getHypervisorType() == HypervisorType.XenServer) {
|
||||
((StartupRoutingCommand) cmd).getHypervisorType() == HypervisorType.XenServer ||
|
||||
((StartupRoutingCommand) cmd).getHypervisorType() == HypervisorType.LXC) {
|
||||
/*TODO: Get the private/public keys here*/
|
||||
|
||||
String pubKey = _configDao.getValue("ssh.publickey");
|
||||
|
|
|
|||
|
|
@ -1527,9 +1527,11 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
|
|||
DomainRouterVO router = deployRouter(owner, destination, plan, params, isRedundant, vrProvider, offeringId,
|
||||
null, networks, false, null);
|
||||
|
||||
_routerDao.addRouterToGuestNetwork(router, guestNetwork);
|
||||
routers.add(router);
|
||||
}
|
||||
if (router != null) {
|
||||
_routerDao.addRouterToGuestNetwork(router, guestNetwork);
|
||||
routers.add(router);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (lock != null) {
|
||||
|
|
|
|||
|
|
@ -747,7 +747,11 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
|
|||
}
|
||||
} else {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Zone host is ready, but secondary storage vm template: " + template.getId() + " is not ready on secondary storage: " + secHost.getId());
|
||||
if (template == null) {
|
||||
s_logger.debug("Zone host is ready, but secondary storage vm template does not exist");
|
||||
} else {
|
||||
s_logger.debug("Zone host is ready, but secondary storage vm template: " + template.getId() + " is not ready on secondary storage: " + secHost.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,6 +141,8 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase implements Te
|
|||
&&(!url.toLowerCase().endsWith("qcow2.bz2"))&&(!url.toLowerCase().endsWith("qcow2.gz"))
|
||||
&&(!url.toLowerCase().endsWith("ova"))&&(!url.toLowerCase().endsWith("ova.zip"))
|
||||
&&(!url.toLowerCase().endsWith("ova.bz2"))&&(!url.toLowerCase().endsWith("ova.gz"))
|
||||
&&(!url.toLowerCase().endsWith("tar"))&&(!url.toLowerCase().endsWith("tar.zip"))
|
||||
&&(!url.toLowerCase().endsWith("tar.bz2"))&&(!url.toLowerCase().endsWith("tar.gz"))
|
||||
&&(!url.toLowerCase().endsWith("img"))&&(!url.toLowerCase().endsWith("raw"))){
|
||||
throw new InvalidParameterValueException("Please specify a valid "+ cmd.getFormat().toLowerCase());
|
||||
}
|
||||
|
|
@ -148,6 +150,7 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase implements Te
|
|||
if ((cmd.getFormat().equalsIgnoreCase("vhd") && (!url.toLowerCase().endsWith("vhd") && !url.toLowerCase().endsWith("vhd.zip") && !url.toLowerCase().endsWith("vhd.bz2") && !url.toLowerCase().endsWith("vhd.gz") ))
|
||||
|| (cmd.getFormat().equalsIgnoreCase("qcow2") && (!url.toLowerCase().endsWith("qcow2") && !url.toLowerCase().endsWith("qcow2.zip") && !url.toLowerCase().endsWith("qcow2.bz2") && !url.toLowerCase().endsWith("qcow2.gz") ))
|
||||
|| (cmd.getFormat().equalsIgnoreCase("ova") && (!url.toLowerCase().endsWith("ova") && !url.toLowerCase().endsWith("ova.zip") && !url.toLowerCase().endsWith("ova.bz2") && !url.toLowerCase().endsWith("ova.gz")))
|
||||
|| (cmd.getFormat().equalsIgnoreCase("tar") && (!url.toLowerCase().endsWith("tar") && !url.toLowerCase().endsWith("tar.zip") && !url.toLowerCase().endsWith("tar.bz2") && !url.toLowerCase().endsWith("tar.gz")))
|
||||
|| (cmd.getFormat().equalsIgnoreCase("raw") && (!url.toLowerCase().endsWith("img") && !url.toLowerCase().endsWith("raw")))) {
|
||||
throw new InvalidParameterValueException("Please specify a valid URL. URL:" + url + " is an invalid for the format " + cmd.getFormat().toLowerCase());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -794,7 +794,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
s_logger.info("The guru did not like the answers so stopping " + vm);
|
||||
}
|
||||
|
||||
StopCommand cmd = new StopCommand(vm.getInstanceName());
|
||||
StopCommand cmd = new StopCommand(vm);
|
||||
StopAnswer answer = (StopAnswer) _agentMgr.easySend(destHostId, cmd);
|
||||
if (answer == null || !answer.getResult()) {
|
||||
s_logger.warn("Unable to stop " + vm + " due to " + (answer != null ? answer.getDetails() : "no answers"));
|
||||
|
|
@ -876,7 +876,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
|
||||
protected <T extends VMInstanceVO> boolean sendStop(VirtualMachineGuru<T> guru, VirtualMachineProfile<T> profile, boolean force) {
|
||||
VMInstanceVO vm = profile.getVirtualMachine();
|
||||
StopCommand stop = new StopCommand(vm, vm.getInstanceName(), null);
|
||||
StopCommand stop = new StopCommand(vm);
|
||||
try {
|
||||
Answer answer = _agentMgr.send(vm.getHostId(), stop);
|
||||
if (!answer.getResult()) {
|
||||
|
|
@ -1061,8 +1061,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
}
|
||||
|
||||
vmGuru.prepareStop(profile);
|
||||
|
||||
StopCommand stop = new StopCommand(vm, vm.getInstanceName(), null);
|
||||
|
||||
StopCommand stop = new StopCommand(vm);
|
||||
boolean stopped = false;
|
||||
StopAnswer answer = null;
|
||||
try {
|
||||
|
|
@ -1380,7 +1380,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
if (!checkVmOnHost(vm, dstHostId)) {
|
||||
s_logger.error("Unable to complete migration for " + vm);
|
||||
try {
|
||||
_agentMgr.send(srcHostId, new Commands(cleanup(vm.getInstanceName())), null);
|
||||
_agentMgr.send(srcHostId, new Commands(cleanup(vm)), null);
|
||||
} catch (AgentUnavailableException e) {
|
||||
s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId);
|
||||
}
|
||||
|
|
@ -1399,7 +1399,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
_alertMgr.sendAlert(alertType, fromHost.getDataCenterId(), fromHost.getPodId(), "Unable to migrate vm " + vm.getInstanceName() + " from host " + fromHost.getName() + " in zone "
|
||||
+ dest.getDataCenter().getName() + " and pod " + dest.getPod().getName(), "Migrate Command failed. Please check logs.");
|
||||
try {
|
||||
_agentMgr.send(dstHostId, new Commands(cleanup(vm.getInstanceName())), null);
|
||||
_agentMgr.send(dstHostId, new Commands(cleanup(vm)), null);
|
||||
} catch (AgentUnavailableException ae) {
|
||||
s_logger.info("Looks like the destination Host is unavailable for cleanup");
|
||||
}
|
||||
|
|
@ -1620,6 +1620,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
return guru.findById(vmId);
|
||||
}
|
||||
|
||||
public Command cleanup(VirtualMachine vm) {
|
||||
return new StopCommand(vm);
|
||||
}
|
||||
|
||||
public Command cleanup(String vmName) {
|
||||
return new StopCommand(vmName);
|
||||
}
|
||||
|
|
@ -1989,7 +1993,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
*/
|
||||
protected Command compareState(long hostId, VMInstanceVO vm, final AgentVmInfo info, final boolean fullSync, boolean trackExternalChange) {
|
||||
State agentState = info.state;
|
||||
final String agentName = info.name;
|
||||
final State serverState = vm.getState();
|
||||
final String serverName = vm.getInstanceName();
|
||||
|
||||
|
|
@ -2092,7 +2095,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
}
|
||||
|
||||
s_logger.debug("State matches but the agent said stopped so let's send a cleanup command anyways.");
|
||||
return cleanup(agentName);
|
||||
return cleanup(vm);
|
||||
}
|
||||
|
||||
if (agentState == State.Shutdowned) {
|
||||
|
|
@ -2110,8 +2113,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
return null;
|
||||
}
|
||||
} else {
|
||||
s_logger.debug("Sending cleanup to a shutdowned vm: " + agentName);
|
||||
command = cleanup(agentName);
|
||||
s_logger.debug("Sending cleanup to a shutdowned vm: " + vm.getInstanceName());
|
||||
command = cleanup(vm);
|
||||
}
|
||||
} else if (agentState == State.Stopped) {
|
||||
// This state means the VM on the agent was detected previously
|
||||
|
|
@ -2129,7 +2132,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
s_logger.debug("Ignoring VM in starting mode: " + vm.getInstanceName());
|
||||
_haMgr.scheduleRestart(vm, false);
|
||||
}
|
||||
command = cleanup(agentName);
|
||||
command = cleanup(vm);
|
||||
} else if (agentState == State.Running) {
|
||||
if (serverState == State.Starting) {
|
||||
if (fullSync) {
|
||||
|
|
@ -2155,7 +2158,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
s_logger.debug("server VM state " + serverState + " does not meet expectation of a running VM report from agent");
|
||||
|
||||
// just be careful not to stop VM for things we don't handle
|
||||
// command = cleanup(agentName);
|
||||
// command = cleanup(vm);
|
||||
}
|
||||
}
|
||||
return command;
|
||||
|
|
|
|||
|
|
@ -393,3 +393,15 @@ CREATE VIEW `cloud`.`account_view` AS
|
|||
|
||||
ALTER TABLE remote_access_vpn ADD COLUMN `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT COMMENT 'id';
|
||||
ALTER TABLE remote_access_vpn ADD COLUMN `uuid` varchar(40) UNIQUE;
|
||||
|
||||
-- START: support for LXC
|
||||
|
||||
INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES ('LXC', 'default', 50, 1);
|
||||
ALTER TABLE `cloud`.`physical_network_traffic_types` ADD COLUMN `lxc_network_label` varchar(255) DEFAULT 'cloudbr0' COMMENT 'The network name label of the physical device dedicated to this traffic on a LXC host';
|
||||
|
||||
UPDATE configuration SET value='KVM,XenServer,VMware,BareMetal,Ovm,LXC' WHERE name='hypervisor.list';
|
||||
|
||||
INSERT INTO `cloud`.`vm_template` (id, unique_name, name, public, created, type, hvm, bits, account_id, url, checksum, enable_password, display_text, format, guest_os_id, featured, cross_zones, hypervisor_type)
|
||||
VALUES (10, 'routing-10', 'SystemVM Template (LXC)', 0, now(), 'SYSTEM', 0, 64, 1, 'http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2', '2755de1f9ef2ce4d6f2bee2efbb4da92', 0, 'SystemVM Template (LXC)', 'QCOW2', 15, 0, 1, 'LXC');
|
||||
|
||||
-- END: support for LXC
|
||||
|
|
|
|||
|
|
@ -114,28 +114,34 @@
|
|||
}
|
||||
});
|
||||
|
||||
if(trafficType.xennetworklabel == null || trafficType.xennetworklabel == 0)
|
||||
trafficType.xennetworklabel = dictionary['label.network.label.display.for.blank.value'];
|
||||
if(trafficType.kvmnetworklabel == null || trafficType.kvmnetworklabel == 0)
|
||||
trafficType.kvmnetworklabel = dictionary['label.network.label.display.for.blank.value'];
|
||||
if(trafficType.vmwarenetworklabel == null || trafficType.vmwarenetworklabel == 0)
|
||||
trafficType.vmwarenetworklabel = dictionary['label.network.label.display.for.blank.value'];
|
||||
if(trafficType.ovmnetworklabel == null || trafficType.ovmnetworklabel == 0)
|
||||
trafficType.ovmnetworklabel = dictionary['label.network.label.display.for.blank.value'];
|
||||
if(trafficType.xennetworklabel == null || trafficType.xennetworklabel == 0)
|
||||
trafficType.xennetworklabel = dictionary['label.network.label.display.for.blank.value'];
|
||||
if(trafficType.kvmnetworklabel == null || trafficType.kvmnetworklabel == 0)
|
||||
trafficType.kvmnetworklabel = dictionary['label.network.label.display.for.blank.value'];
|
||||
if(trafficType.vmwarenetworklabel == null || trafficType.vmwarenetworklabel == 0)
|
||||
trafficType.vmwarenetworklabel = dictionary['label.network.label.display.for.blank.value'];
|
||||
if(trafficType.ovmnetworklabel == null || trafficType.ovmnetworklabel == 0)
|
||||
trafficType.ovmnetworklabel = dictionary['label.network.label.display.for.blank.value'];
|
||||
if(trafficType.lxcnetworklabel == null || trafficType.lxcnetworklabel == 0)
|
||||
trafficType.lxcnetworklabel = dictionary['label.network.label.display.for.blank.value'];
|
||||
|
||||
return trafficType;
|
||||
};
|
||||
|
||||
var updateTrafficLabels = function(trafficType, labels, complete) {
|
||||
var array1 = [];
|
||||
if(labels.xennetworklabel != dictionary['label.network.label.display.for.blank.value'])
|
||||
array1.push("&xennetworklabel=" + labels.xennetworklabel);
|
||||
if(labels.kvmnetworklabel != dictionary['label.network.label.display.for.blank.value'])
|
||||
array1.push("&kvmnetworklabel=" + labels.kvmnetworklabel);
|
||||
if(labels.vmwarenetworklabel != dictionary['label.network.label.display.for.blank.value'])
|
||||
array1.push("&vmwarenetworklabel=" + labels.vmwarenetworklabel);
|
||||
if(labels.ovmnetworklabel != dictionary['label.network.label.display.for.blank.value'])
|
||||
array1.push("&ovmnetworklabel=" + labels.ovmnetworklabel);
|
||||
$.ajax({
|
||||
if(labels.xennetworklabel != dictionary['label.network.label.display.for.blank.value'])
|
||||
array1.push("&xennetworklabel=" + labels.xennetworklabel);
|
||||
if(labels.kvmnetworklabel != dictionary['label.network.label.display.for.blank.value'])
|
||||
array1.push("&kvmnetworklabel=" + labels.kvmnetworklabel);
|
||||
if(labels.vmwarenetworklabel != dictionary['label.network.label.display.for.blank.value'])
|
||||
array1.push("&vmwarenetworklabel=" + labels.vmwarenetworklabel);
|
||||
if(labels.ovmnetworklabel != dictionary['label.network.label.display.for.blank.value'])
|
||||
array1.push("&ovmnetworklabel=" + labels.ovmnetworklabel);
|
||||
if(labels.lxcnetworklabel != dictionary['label.network.label.display.for.blank.value'])
|
||||
array1.push("&lxcnetworklabel=" + labels.lxcnetworklabel);
|
||||
|
||||
$.ajax({
|
||||
url: createURL('updateTrafficType' + array1.join("")),
|
||||
data: {
|
||||
id: trafficType.id
|
||||
|
|
@ -463,7 +469,8 @@
|
|||
xennetworklabel: { label: 'label.xen.traffic.label', isEditable: true },
|
||||
kvmnetworklabel: { label: 'label.kvm.traffic.label', isEditable: true },
|
||||
vmwarenetworklabel: { label: 'label.vmware.traffic.label', isEditable: true },
|
||||
ovmnetworklabel: { label: 'OVM traffic label',isEditable: true }
|
||||
ovmnetworklabel: { label: 'OVM traffic label',isEditable: true },
|
||||
lxcnetworklabel: { label: 'label.lxc.traffic.label',isEditable: true }
|
||||
}
|
||||
],
|
||||
|
||||
|
|
@ -483,6 +490,7 @@
|
|||
selectedPublicNetworkObj.kvmnetworklabel = trafficType.kvmnetworklabel;
|
||||
selectedPublicNetworkObj.vmwarenetworklabel = trafficType.vmwarenetworklabel;
|
||||
selectedPublicNetworkObj.ovmnetworklabel = trafficType.ovmnetworklabel;
|
||||
selectedPublicNetworkObj.lxcnetworklabel = trafficType.lxcnetworklabel;
|
||||
|
||||
args.response.success({data: selectedPublicNetworkObj});
|
||||
}
|
||||
|
|
@ -636,7 +644,8 @@
|
|||
xennetworklabel: { label: 'label.xen.traffic.label', isEditable: true },
|
||||
kvmnetworklabel: { label: 'label.kvm.traffic.label', isEditable: true },
|
||||
vmwarenetworklabel: { label: 'label.vmware.traffic.label', isEditable: true },
|
||||
ovmnetworklabel: { label: 'OVM traffic label', isEditable: true }
|
||||
ovmnetworklabel: { label: 'OVM traffic label', isEditable: true },
|
||||
lxcnetworklabel: { label: 'label.lxc.traffic.label', isEditable: true }
|
||||
}
|
||||
],
|
||||
|
||||
|
|
@ -795,7 +804,8 @@
|
|||
xennetworklabel: { label: 'label.xen.traffic.label', isEditable: true },
|
||||
kvmnetworklabel: { label: 'label.kvm.traffic.label', isEditable: true },
|
||||
vmwarenetworklabel: { label: 'label.vmware.traffic.label', isEditable: true },
|
||||
ovmnetworklabel: { label: 'OVM traffic label', isEditable: true }
|
||||
ovmnetworklabel: { label: 'OVM traffic label', isEditable: true },
|
||||
lxcnetworklabel: { label: 'label.lxc.traffic.label', isEditable: true }
|
||||
}
|
||||
],
|
||||
dataProvider: function(args) {
|
||||
|
|
@ -811,6 +821,7 @@
|
|||
selectedManagementNetworkObj.kvmnetworklabel = trafficType.kvmnetworklabel;
|
||||
selectedManagementNetworkObj.vmwarenetworklabel = trafficType.vmwarenetworklabel;
|
||||
selectedManagementNetworkObj.ovmnetworklabel = trafficType.ovmnetworklabel;
|
||||
selectedManagementNetworkObj.lxcnetworklabel = trafficType.lxcnetworklabel;
|
||||
args.response.success({ data: selectedManagementNetworkObj });
|
||||
}
|
||||
});
|
||||
|
|
@ -928,7 +939,8 @@
|
|||
xennetworklabel: { label: 'label.xen.traffic.label', isEditable: true },
|
||||
kvmnetworklabel: { label: 'label.kvm.traffic.label', isEditable: true },
|
||||
vmwarenetworklabel: { label: 'label.vmware.traffic.label', isEditable: true },
|
||||
ovmnetworklabel: { label: 'OVM traffic label', isEditable: true }
|
||||
ovmnetworklabel: { label: 'OVM traffic label', isEditable: true },
|
||||
lxcnetworklabel: { label: 'label.lxc.traffic.label', isEditable: true }
|
||||
}
|
||||
],
|
||||
dataProvider: function(args) { //physical network + Guest traffic type
|
||||
|
|
@ -964,6 +976,7 @@
|
|||
selectedPhysicalNetworkObj["kvmnetworklabel"] = trafficType.kvmnetworklabel;
|
||||
selectedPhysicalNetworkObj["vmwarenetworklabel"] = trafficType.vmwarenetworklabel;
|
||||
selectedPhysicalNetworkObj["ovmnetworklabel"] = trafficType.ovmnetworklabel;
|
||||
selectedPhysicalNetworkObj["lxcnetworklabel"] = trafficType.lxcnetworklabel;
|
||||
|
||||
args.response.success({
|
||||
actionFilter: function() {
|
||||
|
|
@ -9491,6 +9504,13 @@
|
|||
items.push({id: "ocfs2", description: "ocfs2"});
|
||||
args.response.success({data: items});
|
||||
}
|
||||
else if(selectedClusterObj.hypervisortype == "LXC") {
|
||||
var items = [];
|
||||
items.push({id: "nfs", description: "nfs"});
|
||||
items.push({id: "SharedMountPoint", description: "SharedMountPoint"});
|
||||
items.push({id: "rbd", description: "RBD"});
|
||||
args.response.success({data: items});
|
||||
}
|
||||
else {
|
||||
args.response.success({data:[]});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -237,6 +237,10 @@
|
|||
//formatSelect.append("<option value='RAW'>RAW</option>");
|
||||
items.push({id:'RAW', description: 'RAW'});
|
||||
}
|
||||
else if(args.hypervisor == "LXC") {
|
||||
//formatSelect.append("<option value='TAR'>TAR</option>");
|
||||
items.push({id:'TAR', description: 'TAR'});
|
||||
}
|
||||
args.response.success({data: items});
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@
|
|||
case 'Ovm':
|
||||
hypervisorAttr = 'ovmnetworklabel';
|
||||
break;
|
||||
case 'LXC':
|
||||
hypervisorAttr = 'lxcnetworklabel';
|
||||
break;
|
||||
}
|
||||
|
||||
trafficLabelStr = trafficLabel ? '&' + hypervisorAttr + '=' + trafficLabel : '';
|
||||
|
|
@ -395,6 +398,7 @@
|
|||
nonSupportedHypervisors["VMware"] = 1;
|
||||
nonSupportedHypervisors["BareMetal"] = 1;
|
||||
nonSupportedHypervisors["Ovm"] = 1;
|
||||
nonSupportedHypervisors["LXC"] = 1;
|
||||
}
|
||||
|
||||
if(items != null) {
|
||||
|
|
@ -1256,6 +1260,12 @@
|
|||
items.push({id: "ocfs2", description: "ocfs2"});
|
||||
args.response.success({data: items});
|
||||
}
|
||||
else if(selectedClusterObj.hypervisortype == "LXC") {
|
||||
var items = [];
|
||||
items.push({id: "nfs", description: "nfs"});
|
||||
items.push({id: "SharedMountPoint", description: "SharedMountPoint"});
|
||||
args.response.success({data: items});
|
||||
}
|
||||
else {
|
||||
args.response.success({data:[]});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue