http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aa79ccf9/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java b/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java new file mode 100644 index 0000000..75b007c --- /dev/null +++ b/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java @@ -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(); + } +}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aa79ccf9/server/src/com/cloud/hypervisor/kvm/discoverer/LxcServerDiscoverer.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/hypervisor/kvm/discoverer/LxcServerDiscoverer.java b/server/src/com/cloud/hypervisor/kvm/discoverer/LxcServerDiscoverer.java new file mode 100644 index 0000000..0e6a82b --- /dev/null +++ b/server/src/com/cloud/hypervisor/kvm/discoverer/LxcServerDiscoverer.java @@ -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; + } + +} http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aa79ccf9/server/src/com/cloud/network/SshKeysDistriMonitor.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/SshKeysDistriMonitor.java b/server/src/com/cloud/network/SshKeysDistriMonitor.java index fc7c882..82f72de 100755 --- a/server/src/com/cloud/network/SshKeysDistriMonitor.java +++ b/server/src/com/cloud/network/SshKeysDistriMonitor.java @@ -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"); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aa79ccf9/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index 67c94fc..afdbbca 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -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) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aa79ccf9/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java index 46ac7af..9a4d6b0 100755 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java @@ -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()); + } } } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aa79ccf9/server/src/com/cloud/template/HypervisorTemplateAdapter.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/template/HypervisorTemplateAdapter.java b/server/src/com/cloud/template/HypervisorTemplateAdapter.java index a0444e5..491900b 100755 --- a/server/src/com/cloud/template/HypervisorTemplateAdapter.java +++ b/server/src/com/cloud/template/HypervisorTemplateAdapter.java @@ -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()); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aa79ccf9/server/src/com/cloud/vm/VirtualMachineManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 23746ae..af22716 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -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; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aa79ccf9/setup/db/db/schema-410to420.sql ---------------------------------------------------------------------- diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 53f3c44..3dee7ae 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -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 http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aa79ccf9/ui/scripts/system.js ---------------------------------------------------------------------- diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 9d6c476..98570d2 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -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:[]}); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aa79ccf9/ui/scripts/templates.js ---------------------------------------------------------------------- diff --git a/ui/scripts/templates.js b/ui/scripts/templates.js index 040ce4a..6268f6b 100644 --- a/ui/scripts/templates.js +++ b/ui/scripts/templates.js @@ -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}); } }, http://git-wip-us.apache.org/repos/asf/cloudstack/blob/aa79ccf9/ui/scripts/zoneWizard.js ---------------------------------------------------------------------- diff --git a/ui/scripts/zoneWizard.js b/ui/scripts/zoneWizard.js index a64c86a..76fd5e9 100755 --- a/ui/scripts/zoneWizard.js +++ b/ui/scripts/zoneWizard.js @@ -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:[]}); }
