changes to add a docker host

This commit is contained in:
tuna 2014-03-31 00:56:48 +07:00
parent 018215125b
commit 2ab75245de
11 changed files with 320 additions and 91 deletions

View File

@ -100,6 +100,10 @@ if __name__ == '__main__':
if bridgeType:
glbEnv.bridgeType = bridgeType
hypervisorType = old_config.getEntry("hypervisor.type").lower()
if hypervisorType:
glbEnv.hypervisorType = hypervisorType
(options, args) = parser.parse_args()
if options.auto is None:
userInputs = getUserInputs()

View File

@ -63,7 +63,7 @@ public class AddClusterCmd extends BaseCmd {
required=true, description="the Zone ID for the cluster")
private Long zoneId;
@Parameter(name=ApiConstants.HYPERVISOR, type=CommandType.STRING, required=true, description="hypervisor type of the cluster: XenServer,KVM,VMware,Hyperv,BareMetal,Simulator")
@Parameter(name=ApiConstants.HYPERVISOR, type=CommandType.STRING, required=true, description="hypervisor type of the cluster: XenServer,KVM,VMware,Hyperv,BareMetal,Docker,Simulator")
private String hypervisor;
@Parameter(name=ApiConstants.CLUSTER_TYPE, type=CommandType.STRING, required=true, description="type of the cluster: CloudManaged, ExternalManaged")

View File

@ -57,7 +57,7 @@ public class RegisterTemplateCmd extends BaseCmd {
@Parameter(name=ApiConstants.DISPLAY_TEXT, type=CommandType.STRING, required=true, description="the display text of the template. This is usually used for display purposes.", length=4096)
private String displayText;
@Parameter(name=ApiConstants.FORMAT, type=CommandType.STRING, required=true, description="the format for the template. Possible values include QCOW2, RAW, and VHD.")
@Parameter(name=ApiConstants.FORMAT, type=CommandType.STRING, description="the format for the template. Possible values include QCOW2, RAW, and VHD.")
private String format;
@Parameter(name=ApiConstants.HYPERVISOR, type=CommandType.STRING, required=true, description="the target hypervisor for the template")

View File

@ -15,7 +15,7 @@
<parent>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloudstack-plugins</artifactId>
<version>4.4.0-SNAPSHOT</version>
<version>4.3.0</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<repositories>
@ -23,6 +23,10 @@
<id>libvirt-org</id>
<url>http://libvirt.org/maven2</url>
</repository>
<repository>
<id>ceph-com</id>
<url>http://ceph.com/maven</url>
</repository>
</repositories>
<dependencies>
<dependency>
@ -40,9 +44,9 @@
<version>${cs.libvirt-java.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cloudstack</groupId>
<artifactId>cloud-plugin-network-ovs</artifactId>
<version>${project.version}</version>
<groupId>com.ceph</groupId>
<artifactId>rados</artifactId>
<version>${cs.rados-java.version}</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
@ -58,6 +62,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
@ -75,6 +80,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.14</version>
<configuration>
<excludes>
<exclude>**/Qemu*.java</exclude>

View File

@ -21,17 +21,17 @@ import com.cloud.resource.ServerResourceBase;
@Local(value = {ServerResource.class})
public class DockerResource extends ServerResourceBase implements ServerResource {
private static final Logger s_logger = Logger.getLogger(DockerResource.class);
private static final Logger s_logger = Logger.getLogger(DockerResource.class);
@Override
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
return true;
}
@Override
public Answer executeRequest(Command cmd) {
try {
if (cmd instanceof StopCommand) {
return true;
}
@Override
public Answer executeRequest(Command cmd) {
try {
if (cmd instanceof StopCommand) {
return execute((StopCommand)cmd);
} else if (cmd instanceof RebootCommand) {
return execute((RebootCommand)cmd);
@ -44,72 +44,68 @@ public class DockerResource extends ServerResourceBase implements ServerResource
} catch (final IllegalArgumentException e) {
return new Answer(cmd, false, e.getMessage());
}
}
protected Answer execute(StopCommand cmd) {
}
private Answer execute(RebootCommand cmd) {
}
protected StartAnswer execute(StartCommand cmd) {
}
@Override
public void setName(String name) {
// TODO Auto-generated method stub
}
}
@Override
public void setConfigParams(Map<String, Object> params) {
// TODO Auto-generated method stub
}
protected Answer execute(StopCommand cmd) {
return null;
}
@Override
public Map<String, Object> getConfigParams() {
// TODO Auto-generated method stub
return null;
}
private Answer execute(RebootCommand cmd) {
return null;
}
@Override
public int getRunLevel() {
// TODO Auto-generated method stub
return 0;
}
protected StartAnswer execute(StartCommand cmd) {
return null;
}
@Override
public void setRunLevel(int level) {
// TODO Auto-generated method stub
}
@Override
public Map<String, Object> getConfigParams() {
// TODO Auto-generated method stub
return null;
}
@Override
public Type getType() {
// TODO Auto-generated method stub
return null;
}
@Override
public int getRunLevel() {
// TODO Auto-generated method stub
return 0;
}
@Override
public StartupCommand[] initialize() {
// TODO Auto-generated method stub
return null;
}
@Override
public void setConfigParams(Map<String, Object> arg0) {
// TODO Auto-generated method stub
}
@Override
public PingCommand getCurrentStatus(long id) {
// TODO Auto-generated method stub
return null;
}
@Override
public void setName(String arg0) {
// TODO Auto-generated method stub
}
@Override
protected String getDefaultScriptsDir() {
// TODO Auto-generated method stub
return null;
}
@Override
public void setRunLevel(int arg0) {
// TODO Auto-generated method stub
}
@Override
public PingCommand getCurrentStatus(long arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public Type getType() {
// TODO Auto-generated method stub
return null;
}
@Override
public StartupCommand[] initialize() {
// TODO Auto-generated method stub
return null;
}
@Override
protected String getDefaultScriptsDir() {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -42,6 +42,7 @@
<module>hypervisors/baremetal</module>
<module>hypervisors/ucs</module>
<module>hypervisors/hyperv</module>
<module>hypervisors/docker</module>
<module>network-elements/elastic-loadbalancer</module>
<module>network-elements/ovs</module>
<module>network-elements/juniper-contrail</module>

View File

@ -42,3 +42,5 @@ class globalEnv:
self.distribution = None
# bridgeType
self.bridgeType = "native"
# hypervisorType
self.hypervisorType = None

View File

@ -384,6 +384,10 @@ class nfsConfig(serviceCfgBase):
self.serviceName = "Nfs"
def config(self):
# Docker
if self.syscfg.env.hypervisorType == "docker":
return True
# end Docker
try:
if not os.path.exists("/etc/nfsmount.conf"):
return True
@ -412,6 +416,9 @@ class securityPolicyConfigUbuntu(serviceCfgBase):
self.serviceName = "Apparmor"
def config(self):
# Docker
if self.syscfg.env.hypervisorType == "docker":
return True
try:
cmd = bash("service apparmor status")
if not cmd.isSuccess() or cmd.getStdout() == "":
@ -532,6 +539,9 @@ class libvirtConfigUbuntu(serviceCfgBase):
cfo.replace_or_add_line("libvirtd_opts=","libvirtd_opts='-l -d'")
def config(self):
# Docker
if self.syscfg.env.hypervisorType == "docker":
return True
try:
self.setupLiveMigration()
@ -568,6 +578,9 @@ class firewallConfigUbuntu(serviceCfgBase):
ports = "22 1798 16509".split()
for p in ports:
bash("ufw allow %s"%p)
#Docker
bash("ufw allow 5555")
#end Docker
bash("ufw allow proto tcp from any to any port 5900:6100")
bash("ufw allow proto tcp from any to any port 49152:49216")
self.syscfg.svo.stopService("ufw")
@ -678,7 +691,12 @@ class cloudAgentConfig(serviceCfgBase):
cfo.addEntry("guid", str(self.syscfg.env.uuid))
if cfo.getEntry("local.storage.uuid") == "":
cfo.addEntry("local.storage.uuid", str(bash("uuidgen").getStdout()))
cfo.addEntry("resource", "com.cloud.hypervisor.kvm.resource.LibvirtComputingResource")
# Docker
if self.syscfg.env.hypervisorType == "docker":
cfo.addEntry("resource", "com.cloud.hypervisor.docker.resource.DockerResource")
else:
cfo.addEntry("resource", "com.cloud.hypervisor.kvm.resource.LibvirtComputingResource")
# end Docker
cfo.save()
self.syscfg.svo.stopService("cloudstack-agent")

View File

@ -1,18 +1,218 @@
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.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.configuration.Config;
import com.cloud.dc.ClusterVO;
import com.cloud.exception.DiscoveredWithErrorException;
import com.cloud.exception.DiscoveryException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.network.PhysicalNetworkSetupInfo;
import com.cloud.resource.Discoverer;
import com.cloud.resource.ServerResource;
import com.cloud.utils.ssh.SSHCmdHelper;
@Local(value = Discoverer.class)
public class DockerServerDiscoverer extends LibvirtServerDiscoverer {
private static final Logger s_logger = Logger.getLogger(DockerServerDiscoverer.class);
private String _hostIp;
private final int _waitTime = 5; /* wait for 5 minutes */
private String _dockerPrivateNic;
private String _dockerPublicNic;
private String _dockerGuestNic;
@Override
public Hypervisor.HypervisorType getHypervisorType() {
return Hypervisor.HypervisorType.Docker;
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_dockerPrivateNic = _configDao.getValue(Config.KvmPrivateNetwork.key());
if (_dockerPrivateNic == null) {
_dockerPrivateNic = "cloudbr0";
}
_dockerPublicNic = _configDao.getValue(Config.KvmPublicNetwork.key());
if (_dockerPublicNic == null) {
_dockerPublicNic = _dockerPrivateNic;
}
_dockerGuestNic = _configDao.getValue(Config.KvmGuestNetwork.key());
if (_dockerGuestNic == null) {
_dockerGuestNic = _dockerPrivateNic;
}
_hostIp = _configDao.getValue("host");
if (_hostIp == null) {
throw new ConfigurationException("Can't get host IP");
}
_resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
return true;
}
@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");
}
List<PhysicalNetworkSetupInfo> netInfos = _networkMgr.getPhysicalNetworkInfo(dcId, getHypervisorType());
String dockerPrivateNic = null;
String dockerPublicNic = null;
String dockerGuestNic = null;
for (PhysicalNetworkSetupInfo info : netInfos) {
if (info.getPrivateNetworkName() != null) {
dockerPrivateNic = info.getPrivateNetworkName();
}
if (info.getPublicNetworkName() != null) {
dockerPublicNic = info.getPublicNetworkName();
}
if (info.getGuestNetworkName() != null) {
dockerGuestNic = info.getGuestNetworkName();
}
}
if (dockerPrivateNic == null && dockerPublicNic == null && dockerGuestNic == null) {
dockerPrivateNic = _dockerPrivateNic;
dockerPublicNic = _dockerPublicNic;
dockerGuestNic = _dockerGuestNic;
}
if (dockerPublicNic == null) {
dockerPublicNic = (dockerGuestNic != null) ? dockerGuestNic : dockerPrivateNic;
}
if (dockerPrivateNic == null) {
dockerPrivateNic = (dockerPublicNic != null) ? dockerPublicNic : dockerGuestNic;
}
if (dockerGuestNic == null) {
dockerGuestNic = (dockerPublicNic != null) ? dockerPublicNic : dockerPrivateNic;
}
String parameters = " -m " + _hostIp + " -z " + dcId + " -p " + podId + " -c " + clusterId + " -g " + guid
+ " -a";
parameters += " --pubNic=" + dockerPublicNic;
parameters += " --prvNic=" + dockerPrivateNic;
parameters += " --guestNic=" + dockerGuestNic;
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;
}
}
}

View File

@ -118,17 +118,16 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
@Override
public TemplateProfile prepare(RegisterTemplateCmd cmd) throws ResourceAllocationException {
TemplateProfile profile = super.prepare(cmd);
String url = profile.getUrl();
String path = null;
try {
URL str = new URL(url);
path = str.getPath();
} catch (MalformedURLException ex) {
throw new InvalidParameterValueException("Please specify a valid URL. URL:" + url + " is invalid");
}
// Don't check with Docker template
if (!cmd.getHypervisor().equals(Hypervisor.HypervisorType.Docker)) {
// Don't check with Docker template
if (!HypervisorType.getType(cmd.getHypervisor()).equals(HypervisorType.Docker)) {
String url = profile.getUrl();
String path = null;
try {
URL str = new URL(url);
path = str.getPath();
} catch (MalformedURLException ex) {
throw new InvalidParameterValueException("Please specify a valid URL. URL:" + url + " is invalid");
}
try {
checkFormat(cmd.getFormat(), url);
} catch (InvalidParameterValueException ex) {
@ -139,8 +138,8 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
// Check that the resource limit for secondary storage won't be exceeded
_resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(cmd.getEntityOwnerId()), ResourceType.secondary_storage, UriUtils.getRemoteSize(url));
}
profile.setUrl(url);
}
return profile;
}

View File

@ -187,9 +187,12 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
featured = Boolean.FALSE;
}
ImageFormat imgfmt = ImageFormat.valueOf(format.toUpperCase());
if (imgfmt == null) {
throw new IllegalArgumentException("Image format is incorrect " + format + ". Supported formats are " + EnumUtils.listValues(ImageFormat.values()));
ImageFormat imgfmt = ImageFormat.TAR;
if (!hypervisorType.equals(HypervisorType.Docker)) {
imgfmt = ImageFormat.valueOf(format.toUpperCase());
if (imgfmt == null) {
throw new IllegalArgumentException("Image format is incorrect " + format + ". Supported formats are " + EnumUtils.listValues(ImageFormat.values()));
}
}
// Check that the resource limit for templates/ISOs won't be exceeded