diff --git a/agent/bindir/cloud-setup-agent.in b/agent/bindir/cloud-setup-agent.in
index 6932672b962..667d130e3bf 100755
--- a/agent/bindir/cloud-setup-agent.in
+++ b/agent/bindir/cloud-setup-agent.in
@@ -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()
diff --git a/api/src/org/apache/cloudstack/api/command/admin/cluster/AddClusterCmd.java b/api/src/org/apache/cloudstack/api/command/admin/cluster/AddClusterCmd.java
index e8cb10b770a..92928ae22dc 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/cluster/AddClusterCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/cluster/AddClusterCmd.java
@@ -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")
diff --git a/api/src/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java
index bba90bf2c2a..afdbbb9ec9f 100644
--- a/api/src/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java
@@ -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")
diff --git a/plugins/hypervisors/docker/pom.xml b/plugins/hypervisors/docker/pom.xml
index 4ede673c6ec..1f7a430af11 100755
--- a/plugins/hypervisors/docker/pom.xml
+++ b/plugins/hypervisors/docker/pom.xml
@@ -15,7 +15,7 @@
org.apache.cloudstack
cloudstack-plugins
- 4.4.0-SNAPSHOT
+ 4.3.0
../../pom.xml
@@ -23,6 +23,10 @@
libvirt-org
http://libvirt.org/maven2
+
+ ceph-com
+ http://ceph.com/maven
+
@@ -40,9 +44,9 @@
${cs.libvirt-java.version}
- org.apache.cloudstack
- cloud-plugin-network-ovs
- ${project.version}
+ com.ceph
+ rados
+ ${cs.rados-java.version}
net.java.dev.jna
@@ -58,6 +62,7 @@
org.apache.maven.plugins
maven-dependency-plugin
+ 2.5.1
copy-dependencies
@@ -75,6 +80,7 @@
org.apache.maven.plugins
maven-surefire-plugin
+ 2.14
**/Qemu*.java
diff --git a/plugins/hypervisors/docker/src/com/cloud/hypervisor/docker/resource/DockerResource.java b/plugins/hypervisors/docker/src/com/cloud/hypervisor/docker/resource/DockerResource.java
index 501df0df7eb..6c11e9a63a3 100644
--- a/plugins/hypervisors/docker/src/com/cloud/hypervisor/docker/resource/DockerResource.java
+++ b/plugins/hypervisors/docker/src/com/cloud/hypervisor/docker/resource/DockerResource.java
@@ -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 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 params) {
- // TODO Auto-generated method stub
-
- }
+ protected Answer execute(StopCommand cmd) {
+ return null;
+ }
- @Override
- public Map 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 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 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;
+ }
}
diff --git a/plugins/pom.xml b/plugins/pom.xml
index 86308bc06df..86a7ba839ab 100755
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -42,6 +42,7 @@
hypervisors/baremetal
hypervisors/ucs
hypervisors/hyperv
+ hypervisors/docker
network-elements/elastic-loadbalancer
network-elements/ovs
network-elements/juniper-contrail
diff --git a/python/lib/cloudutils/globalEnv.py b/python/lib/cloudutils/globalEnv.py
index 867aa17670d..9f202122099 100644
--- a/python/lib/cloudutils/globalEnv.py
+++ b/python/lib/cloudutils/globalEnv.py
@@ -42,3 +42,5 @@ class globalEnv:
self.distribution = None
# bridgeType
self.bridgeType = "native"
+ # hypervisorType
+ self.hypervisorType = None
diff --git a/python/lib/cloudutils/serviceConfig.py b/python/lib/cloudutils/serviceConfig.py
index d7c7e78c3ab..7c5c32b6f4d 100755
--- a/python/lib/cloudutils/serviceConfig.py
+++ b/python/lib/cloudutils/serviceConfig.py
@@ -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")
diff --git a/server/src/com/cloud/hypervisor/kvm/discoverer/DockerServerDiscoverer.java b/server/src/com/cloud/hypervisor/kvm/discoverer/DockerServerDiscoverer.java
index d7ce7c20099..7b031d5f5b5 100644
--- a/server/src/com/cloud/hypervisor/kvm/discoverer/DockerServerDiscoverer.java
+++ b/server/src/com/cloud/hypervisor/kvm/discoverer/DockerServerDiscoverer.java
@@ -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 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> find(long dcId, Long podId, Long clusterId, URI uri,
+ String username, String password, List 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> resources = new HashMap>();
+ Map details = new HashMap();
+ 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 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 params = new HashMap();
+
+ 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 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 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 hosts = _resourceMgr.findHostByGuid(dcId, guid);
+ if (hosts.size() == 1) {
+ return hosts.get(0);
+ } else {
+ return null;
+ }
+ }
}
diff --git a/server/src/com/cloud/template/HypervisorTemplateAdapter.java b/server/src/com/cloud/template/HypervisorTemplateAdapter.java
index 32f1287faea..7659b6250ee 100755
--- a/server/src/com/cloud/template/HypervisorTemplateAdapter.java
+++ b/server/src/com/cloud/template/HypervisorTemplateAdapter.java
@@ -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;
}
diff --git a/server/src/com/cloud/template/TemplateAdapterBase.java b/server/src/com/cloud/template/TemplateAdapterBase.java
index c75c1e4137b..510be910fe2 100755
--- a/server/src/com/cloud/template/TemplateAdapterBase.java
+++ b/server/src/com/cloud/template/TemplateAdapterBase.java
@@ -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