You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by tu...@apache.org on 2014/03/30 20:04:16 UTC

[1/7] git commit: updated refs/heads/docker to 2ab7524

Repository: cloudstack
Updated Branches:
  refs/heads/docker [created] 2ab75245d


init docker


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/cd4444cf
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/cd4444cf
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/cd4444cf

Branch: refs/heads/docker
Commit: cd4444cfecc53d2ec5bb0a5774644dc14e517f6d
Parents: 7830a0f
Author: tuna <ng...@gmail.com>
Authored: Mon Mar 17 22:22:05 2014 +0700
Committer: tuna <ng...@gmail.com>
Committed: Sat Mar 29 15:22:23 2014 +0700

----------------------------------------------------------------------
 agent/conf/agent.properties                     |   3 +-
 api/src/com/cloud/hypervisor/Hypervisor.java    |   3 +
 .../com/cloud/upgrade/dao/Upgrade421to430.java  |   6 +
 plugins/hypervisors/docker/pom.xml              |  86 ++++++++++++++
 .../cloudstack/docker-compute/module.properties |  18 +++
 .../spring-docker-compute-context.xml           |  30 +++++
 .../docker/resource/DockerResource.java         | 115 +++++++++++++++++++
 .../lb/InternalLoadBalancerVMManagerImpl.java   |   6 +-
 .../spring-server-compute-context.xml           |   4 +
 .../spring-server-discoverer-context.xml        |   5 +
 server/src/com/cloud/configuration/Config.java  |   2 +-
 server/src/com/cloud/hypervisor/DockerGuru.java |  41 +++++++
 .../kvm/discoverer/DockerServerDiscoverer.java  |  18 +++
 .../kvm/discoverer/LibvirtServerDiscoverer.java |   2 +-
 .../com/cloud/network/SshKeysDistriMonitor.java |   4 +-
 .../router/VirtualNetworkApplianceManager.java  |   6 +-
 .../VirtualNetworkApplianceManagerImpl.java     |   3 +
 setup/db/db/schema-410to420.sql                 |  12 +-
 18 files changed, 354 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/agent/conf/agent.properties
----------------------------------------------------------------------
diff --git a/agent/conf/agent.properties b/agent/conf/agent.properties
old mode 100644
new mode 100755
index 8bd9756..ca3f9e9
--- a/agent/conf/agent.properties
+++ b/agent/conf/agent.properties
@@ -81,12 +81,13 @@ domr.scripts.dir=scripts/network/domr/kvm
 # openvswitch = com.cloud.hypervisor.kvm.resource.OvsVifDriver
 #libvirt.vif.driver=com.cloud.hypervisor.kvm.resource.BridgeVifDriver
 
-# set the hypervisor type, values are: kvm, lxc
+# set the hypervisor type, values are: kvm, lxc, docker
 # hypervisor.type=kvm
 
 # set the hypervisor URI. Usually there is no need for changing this
 # For KVM: qemu:///system
 # For LXC: lxc:///
+# For Docker: docker:///
 # hypervisor.uri=qemu:///system
 
 # settings to enable direct networking in libvirt, should not be used

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/api/src/com/cloud/hypervisor/Hypervisor.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/hypervisor/Hypervisor.java b/api/src/com/cloud/hypervisor/Hypervisor.java
old mode 100644
new mode 100755
index 710ddfc..c574f67
--- a/api/src/com/cloud/hypervisor/Hypervisor.java
+++ b/api/src/com/cloud/hypervisor/Hypervisor.java
@@ -32,6 +32,7 @@ public class Hypervisor {
         Simulator,
         Ovm,
         LXC,
+        Docker,
 
         Any; /*If you don't care about the hypervisor type*/
 
@@ -59,6 +60,8 @@ public class Hypervisor {
                 return HypervisorType.Ovm;
             } else if (hypervisor.equalsIgnoreCase("LXC")) {
                 return HypervisorType.LXC;
+            } else if (hypervisor.equalsIgnoreCase("Docker")) {
+                return HypervisorType.Docker;
             } else if (hypervisor.equalsIgnoreCase("Any")) {
                 return HypervisorType.Any;
             } else {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/engine/schema/src/com/cloud/upgrade/dao/Upgrade421to430.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade421to430.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade421to430.java
old mode 100644
new mode 100755
index 7e26132..7da2863
--- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade421to430.java
+++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade421to430.java
@@ -212,6 +212,8 @@ public class Upgrade421to430 implements DbUpgrade {
                             break;
                         case LXC:       hypervisorsListInUse.add(Hypervisor.HypervisorType.LXC);
                             break;
+                        case Docker:    hypervisorsListInUse.add(Hypervisor.HypervisorType.Docker);
+                        	break;
                     }
                 }
             } catch (SQLException e) {
@@ -223,6 +225,7 @@ public class Upgrade421to430 implements DbUpgrade {
                     put(Hypervisor.HypervisorType.VMware, "systemvm-vmware-4.3");
                     put(Hypervisor.HypervisorType.KVM, "systemvm-kvm-4.3");
                     put(Hypervisor.HypervisorType.LXC, "systemvm-lxc-4.3");
+                    put(Hypervisor.HypervisorType.Docker, "systemvm-docker-4.3");
                     put(Hypervisor.HypervisorType.Hyperv, "systemvm-hyperv-4.3");
                 }
             };
@@ -232,6 +235,7 @@ public class Upgrade421to430 implements DbUpgrade {
                     put(Hypervisor.HypervisorType.VMware, "router.template.vmware");
                     put(Hypervisor.HypervisorType.KVM, "router.template.kvm");
                     put(Hypervisor.HypervisorType.LXC, "router.template.lxc");
+                    put(Hypervisor.HypervisorType.Docker, "router.template.docker");
                     put(Hypervisor.HypervisorType.Hyperv, "router.template.hyperv");
                 }
             };
@@ -241,6 +245,7 @@ public class Upgrade421to430 implements DbUpgrade {
                     put(Hypervisor.HypervisorType.VMware, "http://download.cloud.com/templates/4.3/systemvm64template-2014-01-14-master-vmware.ova");
                     put(Hypervisor.HypervisorType.KVM, "http://download.cloud.com/templates/4.3/systemvm64template-2014-01-14-master-kvm.qcow2.bz2");
                     put(Hypervisor.HypervisorType.LXC, "http://download.cloud.com/templates/4.3/systemvm64template-2014-01-14-master-kvm.qcow2.bz2");
+                    put(Hypervisor.HypervisorType.Docker, "http://download.cloud.com/templates/4.3/systemvm64template-2014-01-14-master-kvm.qcow2.bz2");
                     put(Hypervisor.HypervisorType.Hyperv, "http://download.cloud.com/templates/4.3/systemvm64template-2013-12-23-hyperv.vhd.bz2");
                 }
             };
@@ -250,6 +255,7 @@ public class Upgrade421to430 implements DbUpgrade {
                     put(Hypervisor.HypervisorType.VMware, "ef593a061f3b7594ab0bfd9b0ed0a0d4");
                     put(Hypervisor.HypervisorType.KVM, "85a1bed07bf43cbf022451cb2ecae4ff");
                     put(Hypervisor.HypervisorType.LXC, "85a1bed07bf43cbf022451cb2ecae4ff");
+                    put(Hypervisor.HypervisorType.Docker, "85a1bed07bf43cbf022451cb2ecae4ff");
                     put(Hypervisor.HypervisorType.Hyperv, "5df45ee6ebe1b703a8805f4e1f4d0818");
                 }
             };

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/plugins/hypervisors/docker/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/docker/pom.xml b/plugins/hypervisors/docker/pom.xml
new file mode 100755
index 0000000..4ede673
--- /dev/null
+++ b/plugins/hypervisors/docker/pom.xml
@@ -0,0 +1,86 @@
+<!-- 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. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>cloud-plugin-hypervisor-docker</artifactId>
+  <name>Apache CloudStack Plugin - Hypervisor Docker</name>
+  <parent>
+    <groupId>org.apache.cloudstack</groupId>
+    <artifactId>cloudstack-plugins</artifactId>
+    <version>4.4.0-SNAPSHOT</version>
+    <relativePath>../../pom.xml</relativePath>
+  </parent>
+  <repositories>
+    <repository>
+      <id>libvirt-org</id>
+      <url>http://libvirt.org/maven2</url>
+    </repository>
+  </repositories>
+  <dependencies>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cloudstack</groupId>
+      <artifactId>cloud-agent</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.libvirt</groupId>
+      <artifactId>libvirt</artifactId>
+      <version>${cs.libvirt-java.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cloudstack</groupId>
+      <artifactId>cloud-plugin-network-ovs</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>net.java.dev.jna</groupId>
+       <artifactId>jna</artifactId>
+       <version>${cs.jna.version}</version>
+    </dependency>
+  </dependencies>
+  <build>
+    <defaultGoal>install</defaultGoal>
+    <sourceDirectory>src</sourceDirectory>
+    <testSourceDirectory>test</testSourceDirectory>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>copy-dependencies</id>
+            <phase>package</phase>
+            <goals>
+              <goal>copy-dependencies</goal>
+            </goals>
+            <configuration>
+              <outputDirectory>${project.build.directory}/dependencies</outputDirectory>
+              <includeScope>runtime</includeScope>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <excludes>
+            <exclude>**/Qemu*.java</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/plugins/hypervisors/docker/resources/META-INF/cloudstack/docker-compute/module.properties
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/docker/resources/META-INF/cloudstack/docker-compute/module.properties b/plugins/hypervisors/docker/resources/META-INF/cloudstack/docker-compute/module.properties
new file mode 100755
index 0000000..0da362b
--- /dev/null
+++ b/plugins/hypervisors/docker/resources/META-INF/cloudstack/docker-compute/module.properties
@@ -0,0 +1,18 @@
+# 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.
+name=docker-compute
+parent=compute
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/plugins/hypervisors/docker/resources/META-INF/cloudstack/docker-compute/spring-docker-compute-context.xml
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/docker/resources/META-INF/cloudstack/docker-compute/spring-docker-compute-context.xml b/plugins/hypervisors/docker/resources/META-INF/cloudstack/docker-compute/spring-docker-compute-context.xml
new file mode 100755
index 0000000..77c549f
--- /dev/null
+++ b/plugins/hypervisors/docker/resources/META-INF/cloudstack/docker-compute/spring-docker-compute-context.xml
@@ -0,0 +1,30 @@
+<!--
+  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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns:aop="http://www.springframework.org/schema/aop"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+                      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
+                      http://www.springframework.org/schema/context
+                      http://www.springframework.org/schema/context/spring-context-3.0.xsd"
+                      >
+
+</beans>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/plugins/hypervisors/docker/src/com/cloud/hypervisor/docker/resource/DockerResource.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
new file mode 100644
index 0000000..501df0d
--- /dev/null
+++ b/plugins/hypervisors/docker/src/com/cloud/hypervisor/docker/resource/DockerResource.java
@@ -0,0 +1,115 @@
+package com.cloud.hypervisor.docker.resource;
+
+import java.util.Map;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.PingCommand;
+import com.cloud.agent.api.RebootCommand;
+import com.cloud.agent.api.StartAnswer;
+import com.cloud.agent.api.StartCommand;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StopCommand;
+import com.cloud.host.Host.Type;
+import com.cloud.resource.ServerResource;
+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);
+
+	@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 execute((StopCommand)cmd);
+            } else if (cmd instanceof RebootCommand) {
+                return execute((RebootCommand)cmd);
+            }  else if (cmd instanceof StartCommand) {
+                return execute((StartCommand)cmd);
+            }  else {
+                s_logger.warn("Unsupported command ");
+                return Answer.createUnsupportedCommandAnswer(cmd);
+            }
+        } 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
+		
+	}
+
+	@Override
+	public Map<String, Object> getConfigParams() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public int getRunLevel() {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	@Override
+	public void setRunLevel(int level) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public Type getType() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public StartupCommand[] initialize() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public PingCommand getCurrentStatus(long id) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	protected String getDefaultScriptsDir() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+	
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java
old mode 100644
new mode 100755
index 02e872b..86f2860
--- a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java
+++ b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/lb/InternalLoadBalancerVMManagerImpl.java
@@ -749,7 +749,11 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements In
                     case LXC:
                         templateName = VirtualNetworkApplianceManager.RouterTemplateLxc.valueIn(dest.getDataCenter().getId());
                         break;
-                    default: break;
+                    case Docker:
+                        templateName = VirtualNetworkApplianceManager.RouterTemplateDocker.valueIn(dest.getDataCenter().getId());
+                        break;
+                    default:
+                        break;
                 }
                 VMTemplateVO template = _templateDao.findRoutingTemplate(hType, templateName);
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/server/resources/META-INF/cloudstack/server-compute/spring-server-compute-context.xml
----------------------------------------------------------------------
diff --git a/server/resources/META-INF/cloudstack/server-compute/spring-server-compute-context.xml b/server/resources/META-INF/cloudstack/server-compute/spring-server-compute-context.xml
old mode 100644
new mode 100755
index 1311902..d1667eb
--- a/server/resources/META-INF/cloudstack/server-compute/spring-server-compute-context.xml
+++ b/server/resources/META-INF/cloudstack/server-compute/spring-server-compute-context.xml
@@ -34,5 +34,9 @@
     <bean id="LXCGuru" class="com.cloud.hypervisor.LXCGuru">
         <property name="name" value="LXCGuru" />
     </bean>
+    
+    <bean id="DockerGuru" class="com.cloud.hypervisor.DockerGuru">
+        <property name="name" value="DockerGuru" />
+    </bean>
 
 </beans>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/server/resources/META-INF/cloudstack/server-discoverer/spring-server-discoverer-context.xml
----------------------------------------------------------------------
diff --git a/server/resources/META-INF/cloudstack/server-discoverer/spring-server-discoverer-context.xml b/server/resources/META-INF/cloudstack/server-discoverer/spring-server-discoverer-context.xml
old mode 100644
new mode 100755
index 90666d1..3b2a948
--- a/server/resources/META-INF/cloudstack/server-discoverer/spring-server-discoverer-context.xml
+++ b/server/resources/META-INF/cloudstack/server-discoverer/spring-server-discoverer-context.xml
@@ -37,6 +37,11 @@
         class="com.cloud.hypervisor.kvm.discoverer.LxcServerDiscoverer">
         <property name="name" value="Lxc Discover" />
     </bean>
+    
+    <bean id="DockerServerDiscoverer"
+        class="com.cloud.hypervisor.kvm.discoverer.DockerServerDiscoverer">
+        <property name="name" value="Docker Discover" />
+    </bean>    
 
     <bean id="dummyHostDiscoverer" class="com.cloud.resource.DummyHostDiscoverer">
         <property name="name" value="dummyHostDiscoverer" />

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/server/src/com/cloud/configuration/Config.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java
index 6ebb7e6..feaee2f 100755
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -178,7 +178,7 @@ public enum Config {
 	SystemVMDefaultHypervisor("Advanced", ManagementServer.class, String.class, "system.vm.default.hypervisor", null, "Hypervisor type used to create system vm", null),
     SystemVMRandomPassword("Advanced", ManagementServer.class, Boolean.class, "system.vm.random.password", "false", "Randomize system vm password the first time management server starts", null),
 	LinkLocalIpNums("Advanced", ManagementServer.class, Integer.class, "linkLocalIp.nums", "10", "The number of link local ip that needed by domR(in power of 2)", null),
-	HypervisorList("Advanced", ManagementServer.class, String.class, "hypervisor.list", HypervisorType.Hyperv + "," + HypervisorType.KVM + "," + HypervisorType.XenServer + "," + HypervisorType.VMware + "," + HypervisorType.BareMetal + "," + HypervisorType.Ovm + "," + HypervisorType.LXC, "The list of hypervisors that this deployment will use.", "hypervisorList"),
+	HypervisorList("Advanced", ManagementServer.class, String.class, "hypervisor.list", HypervisorType.Hyperv + "," + HypervisorType.KVM + "," + HypervisorType.XenServer + "," + HypervisorType.VMware + "," + HypervisorType.BareMetal + "," + HypervisorType.Ovm + "," + HypervisorType.LXC + "," + HypervisorType.Docker, "The list of hypervisors that this deployment will use.", "hypervisorList"),
 	ManagementNetwork("Advanced", ManagementServer.class, String.class, "management.network.cidr", null, "The cidr of management server network", null),
 	EventPurgeDelay("Advanced", ManagementServer.class, Integer.class, "event.purge.delay", "15", "Events older than specified number days will be purged. Set this value to 0 to never delete events", null),
 	SecStorageVmMTUSize("Advanced", AgentManager.class, Integer.class, "secstorage.vm.mtu.size", String.valueOf(SecondaryStorageVmManager.DEFAULT_SS_VM_MTUSIZE), "MTU size (in Byte) of storage network in secondary storage vms", null),

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/server/src/com/cloud/hypervisor/DockerGuru.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/hypervisor/DockerGuru.java b/server/src/com/cloud/hypervisor/DockerGuru.java
new file mode 100644
index 0000000..bba6927
--- /dev/null
+++ b/server/src/com/cloud/hypervisor/DockerGuru.java
@@ -0,0 +1,41 @@
+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.VirtualMachineProfile;
+
+@Local(value = HypervisorGuru.class)
+public class DockerGuru extends HypervisorGuruBase implements HypervisorGuru {
+    @Inject
+    GuestOSDao _guestOsDao;
+
+    @Override
+    public HypervisorType getHypervisorType() {
+        return HypervisorType.Docker;
+    }
+    
+    protected DockerGuru() {
+        super();
+    }
+
+    @Override
+    public VirtualMachineTO implement(VirtualMachineProfile vm) {
+        VirtualMachineTO to = toVirtualMachineTO(vm);
+
+        // Determine the VM's OS description
+        GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId());
+        to.setOs(guestOS.getDisplayName());
+
+        return to;
+    }
+    
+    @Override
+    public boolean trackVmHostChange() {
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/server/src/com/cloud/hypervisor/kvm/discoverer/DockerServerDiscoverer.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/hypervisor/kvm/discoverer/DockerServerDiscoverer.java b/server/src/com/cloud/hypervisor/kvm/discoverer/DockerServerDiscoverer.java
new file mode 100644
index 0000000..558aa25
--- /dev/null
+++ b/server/src/com/cloud/hypervisor/kvm/discoverer/DockerServerDiscoverer.java
@@ -0,0 +1,18 @@
+package com.cloud.hypervisor.kvm.discoverer;
+
+import javax.ejb.Local;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.hypervisor.Hypervisor;
+import com.cloud.resource.Discoverer;
+
+@Local(value = Discoverer.class)
+public class DockerServerDiscoverer extends LibvirtServerDiscoverer {
+	private static final Logger s_logger = Logger.getLogger(DockerServerDiscoverer.class);
+
+    @Override
+    public Hypervisor.HypervisorType getHypervisorType() {
+        return Hypervisor.HypervisorType.Docker;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/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
old mode 100644
new mode 100755
index d7b5ab8..12bcfea
--- a/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java
+++ b/server/src/com/cloud/hypervisor/kvm/discoverer/LibvirtServerDiscoverer.java
@@ -384,7 +384,7 @@ public abstract class LibvirtServerDiscoverer extends DiscovererBase implements
     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)) {
+                || (host.getHypervisorType() != HypervisorType.KVM && host.getHypervisorType() != HypervisorType.LXC && host.getHypervisorType() != HypervisorType.Docker)) {
             return null;
         }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/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 6920062..ff096f2 100755
--- a/server/src/com/cloud/network/SshKeysDistriMonitor.java
+++ b/server/src/com/cloud/network/SshKeysDistriMonitor.java
@@ -37,7 +37,6 @@ import com.cloud.host.Status;
 import com.cloud.host.dao.HostDao;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 
-
 public class SshKeysDistriMonitor implements Listener {
 	  private static final Logger s_logger = Logger.getLogger(SshKeysDistriMonitor.class);
 	  	AgentManager _agentMgr;
@@ -74,7 +73,8 @@ public class SshKeysDistriMonitor implements Listener {
 	    	if (cmd instanceof StartupRoutingCommand) {
 	    		if (((StartupRoutingCommand) cmd).getHypervisorType() == HypervisorType.KVM ||
                     ((StartupRoutingCommand) cmd).getHypervisorType() == HypervisorType.XenServer ||
-                    ((StartupRoutingCommand) cmd).getHypervisorType() == HypervisorType.LXC) {
+                    ((StartupRoutingCommand) cmd).getHypervisorType() == HypervisorType.LXC ||
+                    ((StartupRoutingCommand)cmd).getHypervisorType() == HypervisorType.Docker) {
 	    			/*TODO: Get the private/public keys here*/
 	    			
 	    			String pubKey = _configDao.getValue("ssh.publickey");

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java
old mode 100644
new mode 100755
index 4ea09e5..c2f43b8
--- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java
+++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java
@@ -50,6 +50,8 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA
     static final String RouterTemplateVmwareCK = "router.template.vmware";
     static final String RouterTemplateHyperVCK = "router.template.hyperv";
     static final String RouterTemplateLxcCK = "router.template.lxc";
+    static final String RouterTemplateDockerCK = "router.template.docker";    
+    static final String SetServiceMonitorCK = "network.router.EnableServiceMonitoring";
 
     static final ConfigKey<String> RouterTemplateXen = new ConfigKey<String>(String.class, RouterTemplateXenCK, "Advanced", "SystemVM Template (XenServer)",
         "Name of the default router template on Xenserver.", true, ConfigKey.Scope.Zone, null);
@@ -60,7 +62,9 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA
     static final ConfigKey<String> RouterTemplateHyperV = new ConfigKey<String>(String.class, RouterTemplateHyperVCK, "Advanced", "SystemVM Template (HyperV)",
         "Name of the default router template on Hyperv.", true, ConfigKey.Scope.Zone, null);
     static final ConfigKey<String> RouterTemplateLxc = new ConfigKey<String>(String.class, RouterTemplateLxcCK, "Advanced", "SystemVM Template (LXC)",
-        "Name of the default router template on LXC.", true, ConfigKey.Scope.Zone, null);
+            "Name of the default router template on LXC.", true, ConfigKey.Scope.Zone, null);
+    static final ConfigKey<String> RouterTemplateDocker = new ConfigKey<String>(String.class, RouterTemplateDockerCK, "Advanced", "SystemVM Template (Docker)",
+            "Name of the default router template on Docker.", true, ConfigKey.Scope.Zone, null);
 
     public static final int DEFAULT_ROUTER_VM_RAMSIZE = 128;            // 128M
     public static final int DEFAULT_ROUTER_CPU_MHZ = 500;            	// 500 MHz

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/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 466b861..0aeba4d 100755
--- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -1666,6 +1666,9 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V
                     case LXC:
                         templateName = RouterTemplateLxc.valueIn(dest.getDataCenter().getId());
                         break;
+                    case Docker:
+                        templateName = RouterTemplateDocker.valueIn(dest.getDataCenter().getId());
+                        break;
                     default: break;
                 }
                 VMTemplateVO template = _templateDao.findRoutingTemplate(hType, templateName);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd4444cf/setup/db/db/schema-410to420.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql
old mode 100644
new mode 100755
index b0be6c7..9af1162
--- a/setup/db/db/schema-410to420.sql
+++ b/setup/db/db/schema-410to420.sql
@@ -661,19 +661,24 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Project Defaults', 'DEFAULT'
 ALTER TABLE `cloud`.`remote_access_vpn` ADD COLUMN `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT COMMENT 'id';
 ALTER TABLE `cloud`.`remote_access_vpn` ADD COLUMN `uuid` varchar(40) UNIQUE;
 
--- START: support for LXC
+-- START: support for LXC and Docker
  
 INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(uuid, hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES (UUID(), 'LXC', 'default', 50, 1);
+INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(uuid, hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES (UUID(), 'Docker', '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';
+ALTER TABLE `cloud`.`physical_network_traffic_types` ADD COLUMN `docker_network_label` varchar(255) DEFAULT 'cloudbr0' COMMENT 'The network name label of the physical device dedicated to this traffic on a Docker host';
  
-UPDATE configuration SET value='KVM,XenServer,VMware,BareMetal,Ovm,LXC' WHERE name='hypervisor.list';
+UPDATE configuration SET value='KVM,XenServer,VMware,BareMetal,Ovm,LXC,Docker' WHERE name='hypervisor.list';
  
 INSERT INTO `cloud`.`vm_template` (id, uuid, 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, UUID(), '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');
+INSERT INTO `cloud`.`vm_template` (id, uuid, 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, UUID(), 'routing-10', 'SystemVM Template (Docker)', 0, now(), 'SYSTEM', 0, 64, 1, 'http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2', '2755de1f9ef2ce4d6f2bee2efbb4da92', 0, 'SystemVM Template (Docker)', 'QCOW2', 15, 0, 1, 'Docker');
 
 ALTER TABLE `cloud`.`user_vm` MODIFY user_data TEXT(32768);
 
--- END: support for LXC
+-- END: support for LXC and Docker
 
 CREATE TABLE `cloud`.`vm_snapshots` (
   `id` bigint(20) unsigned NOT NULL auto_increment COMMENT 'Primary Key',
@@ -2178,6 +2183,7 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'manag
 INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'NetworkManager', 'router.template.hyperv', 'SystemVM Template (HyperV)', 'Name of the default router template on Hyperv.');
 INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'NetworkManager', 'router.template.kvm', 'SystemVM Template (KVM)', 'Name of the default router template on KVM.');
 INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'NetworkManager', 'router.template.lxc', 'SystemVM Template (LXC)', 'Name of the default router template on LXC.');
+INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'NetworkManager', 'router.template.docker', 'SystemVM Template (Docker)', 'Name of the default router template on Docker.');
 INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'NetworkManager', 'router.template.vmware', 'SystemVM Template (vSphere)', 'Name of the default router template on Vmware.');
 INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'NetworkManager', 'router.template.xen', 'SystemVM Template (XenServer)', 'Name of the default router template on Xenserver.');
 


[4/7] git commit: updated refs/heads/docker to 2ab7524

Posted by tu...@apache.org.
add docker client


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/cd8a4520
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/cd8a4520
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/cd8a4520

Branch: refs/heads/docker
Commit: cd8a4520b7e02ad91245f0b4e2191a60c28e1bad
Parents: cd4444c
Author: tuna <ng...@gmail.com>
Authored: Wed Mar 26 02:45:37 2014 +0700
Committer: tuna <ng...@gmail.com>
Committed: Sat Mar 29 15:24:06 2014 +0700

----------------------------------------------------------------------
 docker-java/.gitignore                          |  21 +
 docker-java/LICENSE                             | 202 +++++
 docker-java/README.md                           | 114 +++
 docker-java/pom.xml                             | 292 +++++++
 .../com/google/common/base/Preconditions.java   | 443 +++++++++++
 .../com/kpelykh/docker/client/DockerClient.java | 767 ++++++++++++++++++
 .../kpelykh/docker/client/DockerException.java  |  25 +
 .../docker/client/NotFoundException.java        |  20 +
 .../kpelykh/docker/client/UnixSocketClient.java |  12 +
 .../docker/client/UnixSocketClientHandler.java  | 213 +++++
 .../client/UnixSocketSessionInputBuffer.java    |  23 +
 .../client/UnixSocketSessionOutputBuffer.java   |  17 +
 .../docker/client/model/BoundHostVolumes.java   |  93 +++
 .../kpelykh/docker/client/model/ChangeLog.java  |  33 +
 .../docker/client/model/CommitConfig.java       |  85 ++
 .../kpelykh/docker/client/model/Container.java  | 140 ++++
 .../docker/client/model/ContainerConfig.java    | 282 +++++++
 .../client/model/ContainerCreateResponse.java   |  43 +
 .../client/model/ContainerInspectResponse.java  | 247 ++++++
 .../kpelykh/docker/client/model/CopyConfig.java |  61 ++
 .../docker/client/model/DriverStatus.java       |  31 +
 .../kpelykh/docker/client/model/HostConfig.java | 148 ++++
 .../kpelykh/docker/client/model/IBuilder.java   |   9 +
 .../com/kpelykh/docker/client/model/Image.java  | 116 +++
 .../client/model/ImageCreateResponse.java       |  30 +
 .../client/model/ImageInspectResponse.java      | 150 ++++
 .../com/kpelykh/docker/client/model/Info.java   | 225 ++++++
 .../com/kpelykh/docker/client/model/Port.java   |  52 ++
 .../com/kpelykh/docker/client/model/Ports.java  | 131 +++
 .../kpelykh/docker/client/model/SearchItem.java |  52 ++
 .../kpelykh/docker/client/model/Version.java    |  91 +++
 .../client/utils/CompressArchiveUtil.java       |  59 ++
 .../docker/client/utils/JsonClientFilter.java   |  26 +
 .../docker/client/test/DockerClientTest.java    | 791 +++++++++++++++++++
 docker-java/src/test/resources/logback.xml      |  16 +
 .../src/test/resources/netcat/Dockerfile        |  11 +
 docker-java/src/test/resources/nginx/Dockerfile |  12 +
 .../src/test/resources/testAddFile/Dockerfile   |   9 +
 .../src/test/resources/testAddFile/testrun.sh   |   3 +
 .../src/test/resources/testAddFolder/Dockerfile |  11 +
 .../testAddFolder/folderA/testAddFolder.sh      |   3 +
 .../resources/testImportImageFromTar/empty.tar  | Bin 0 -> 10240 bytes
 pom.xml                                         |   5 +
 43 files changed, 5114 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/.gitignore
----------------------------------------------------------------------
diff --git a/docker-java/.gitignore b/docker-java/.gitignore
new file mode 100644
index 0000000..8613949
--- /dev/null
+++ b/docker-java/.gitignore
@@ -0,0 +1,21 @@
+#Ignore Mac OS X DS Store
+.DS_Store
+
+*~
+*.swp
+.project
+.settings
+.classpath
+
+# Ignore all build/dist directories
+target
+
+# Ignore InteliJ Idea project files
+.idea
+.idea/*
+*.iml
+*.iws
+*.ipr
+
+# Ignore all log files
+*.log

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/LICENSE
----------------------------------------------------------------------
diff --git a/docker-java/LICENSE b/docker-java/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/docker-java/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/README.md
----------------------------------------------------------------------
diff --git a/docker-java/README.md b/docker-java/README.md
new file mode 100644
index 0000000..2dd43ec
--- /dev/null
+++ b/docker-java/README.md
@@ -0,0 +1,114 @@
+# docker-java
+
+Java API client for [Docker](http://docs.docker.io/ "Docker")
+
+Supports a subset of the Docker Client API v1.8, Docker Server version 0.8.1
+
+## Build with Maven
+
+###### Prerequisites:
+
+* Java 1.6+
+* Maven 3.0.5
+* Docker daemon running
+
+Maven will run tests during build process. Tests are using localhost instance of Docker, make sure that
+you have Docker running for tests to work or just turn off tests.
+
+If you don't have Docker running locally, you can skip tests with -DskipTests flag set to true:
+
+    $ mvn clean install -DskipTests=true
+
+
+By default Docker server is using UNIX sockets for communication with the Docker client, however docker-java
+client uses TCP/IP to connect to the Docker server, so you will need to make sure that your Docker server is
+listening on TCP port. To allow Docker server to use TCP add the following line to /etc/default/docker
+
+    DOCKER_OPTS="-H tcp://127.0.0.1:4243 -H unix:///var/run/docker.sock"
+
+More details setting up docket server can be found in official documentation: http://docs.docker.io/en/latest/use/basics/
+
+Now make sure that docker is up:
+    
+    $ docker -H tcp://127.0.0.1:4243 version
+
+    Client version: 0.8.1
+    Go version (client): go1.2
+    Git commit (client): a1598d1
+    Server version: 0.8.1
+    Git commit (server): a1598d1
+    Go version (server): go1.2
+    Last stable version: 0.8.1
+
+Run build with tests:
+
+    $ mvn clean install
+
+## Docker-Java maven dependency:
+
+    <dependency>
+          <groupId>com.kpelykh</groupId>
+          <artifactId>docker-java</artifactId>
+          <version>0.8.1</version>
+    </dependency>
+
+
+## Example code snippets:
+
+    DockerClient dockerClient = new DockerClient("http://localhost:4243");
+
+###### Get Docker info:
+
+    Info info = dockerClient.info();
+    System.out.print(info);
+    
+###### Search Docker repository:
+
+    List<SearchItem> dockerSearch = dockerClient.search("busybox");
+    System.out.println("Search returned" + dockerSearch.toString());
+      
+###### Create new Docker container, wait for its start and stop it:
+
+    ContainerConfig containerConfig = new ContainerConfig();
+    containerConfig.setImage("busybox");
+    containerConfig.setCmd(new String[] {"touch", "/test"});
+    ContainerCreateResponse container = dockerClient.createContainer(containerConfig);
+
+    dockerClient.startContainer(container.id);
+
+    dockerClient.waitContainer(container.id);
+
+    dockerClient.stopContainer(container.id);
+    
+
+##### Support for UNIX sockets:
+
+    Support for UNIX socket should appear in docker-java pretty soon. I'm working on its integration.
+
+##### Docker Builder:
+
+To use Docker Builder, as described on page http://docs.docker.io/en/latest/use/builder/,
+user dockerClient.build(baseDir), where baseDir is a path to folder containing Dockerfile.
+
+
+    File baseDir = new File("~/kpelykh/docker/netcat");
+
+    ClientResponse response = dockerClient.build(baseDir);
+
+    StringWriter logwriter = new StringWriter();
+
+    try {
+        LineIterator itr = IOUtils.lineIterator(response.getEntityInputStream(), "UTF-8");
+        while (itr.hasNext()) {
+            String line = itr.next();
+            logwriter.write(line);
+            LOG.info(line);
+        }
+    } finally {
+        IOUtils.closeQuietly(response.getEntityInputStream());
+    }
+
+
+
+For additional examples, please look at [DockerClientTest.java](https://github.com/kpelykh/docker-java/blob/master/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java "DockerClientTest.java")
+

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/pom.xml
----------------------------------------------------------------------
diff --git a/docker-java/pom.xml b/docker-java/pom.xml
new file mode 100644
index 0000000..03125eb
--- /dev/null
+++ b/docker-java/pom.xml
@@ -0,0 +1,292 @@
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+   <parent>
+    <groupId>org.apache.cloudstack</groupId>
+    <artifactId>cloudstack</artifactId>
+    <version>4.4.0-SNAPSHOT</version>
+    <relativePath>../pom.xml</relativePath>
+   </parent>
+
+    <groupId>com.kpelykh</groupId>
+    <artifactId>docker-java</artifactId>
+    <packaging>jar</packaging>
+    <version>0.8.2-SNAPSHOT</version>
+
+    <name>docker-java</name>
+    <url>https://github.com/kpelykh/docker-java</url>
+    <description>Java API Client for Docker</description>
+
+    <scm>
+        <connection>scm:git:git@github.com:kpelykh/docker-java.git</connection>
+        <url>git@github.com:kpelykh/docker-java.git</url>
+        <developerConnection>scm:git:git@github.com:kpelykh/docker-java.git</developerConnection>
+    <tag>HEAD</tag>
+  </scm>
+
+    <developers>
+        <developer>
+            <id>kpelykh</id>
+            <name>Konstantin Pelykh</name>
+            <email>kpelykh@gmail.com</email>
+        </developer>
+    </developers>
+
+    <properties>
+        <skipTests>true</skipTests>
+
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <jdk.debug>true</jdk.debug>
+        <jdk.optimize>false</jdk.optimize>
+        <jdk.source>1.6</jdk.source>
+        <jdk.target>1.6</jdk.target>
+
+        <version.slf4j>1.6.1</version.slf4j>
+
+        <jersey.version>1.18</jersey.version>
+        <jersey-apache-client4.version>1.9</jersey-apache-client4.version>
+
+        <httpclient.version>4.2.5</httpclient.version>
+        <commons-compress.version>1.5</commons-compress.version>
+        <commons-io.version>2.3</commons-io.version>
+        <commons-lang.version>2.6</commons-lang.version>
+        <slf4j-api.version>1.7.5</slf4j-api.version>
+        <jsr305.version>1.3.9</jsr305.version>
+        <jnr.unixsocket.version>0.3</jnr.unixsocket.version>
+
+        <!--test dependencies -->
+        <version.logback>1.0.1</version.logback>
+        <version.testng>5.12.1</version.testng>
+        <hamcrest.library.version>1.3</hamcrest.library.version>
+        <hamcrest.jpa-matchers>1.6</hamcrest.jpa-matchers>
+        <lambdaj.version>2.3.3</lambdaj.version>
+
+
+        <maven-jar-plugin.version>2.2</maven-jar-plugin.version>
+        <maven-compiler-plugin.version>2.3.1</maven-compiler-plugin.version>
+        <maven-release-plugin.version>2.3.1</maven-release-plugin.version>
+        <maven-surefire-plugin.version>2.8.1</maven-surefire-plugin.version>
+        <cobertura-maven-plugin.version>2.5.1</cobertura-maven-plugin.version>
+        <maven-antrun-plugin.version>1.7</maven-antrun-plugin.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.sun.jersey</groupId>
+            <artifactId>jersey-core</artifactId>
+            <version>${jersey.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.jersey</groupId>
+            <artifactId>jersey-client</artifactId>
+            <version>${jersey.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.jersey</groupId>
+            <artifactId>jersey-json</artifactId>
+            <version>${jersey.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.jersey.contribs</groupId>
+            <artifactId>jersey-multipart</artifactId>
+            <version>${jersey.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.jersey.contribs</groupId>
+            <artifactId>jersey-apache-client4</artifactId>
+            <version>${jersey-apache-client4.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>${httpclient.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-compress</artifactId>
+            <version>${commons-compress.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>${commons-lang.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>${commons-io.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.jnr</groupId>
+            <artifactId>jnr-unixsocket</artifactId>
+            <version>${jnr.unixsocket.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>${slf4j-api.version}</version>
+        </dependency>
+
+        <!-- /// Test /////////////////////////// -->
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-core</artifactId>
+            <version>${version.logback}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>${version.logback}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <version>${version.testng}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-library</artifactId>
+            <version>${hamcrest.library.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.googlecode.lambdaj</groupId>
+            <artifactId>lambdaj</artifactId>
+            <version>${lambdaj.version}</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.hamcrest</groupId>
+                    <artifactId>hamcrest-all</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.testinfected.hamcrest-matchers</groupId>
+            <artifactId>jpa-matchers</artifactId>
+            <version>${hamcrest.jpa-matchers}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+
+    <build>
+	  <pluginManagement>
+        <plugins>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-release-plugin</artifactId>
+                <version>${maven-release-plugin.version}</version>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>${maven-compiler-plugin.version}</version>
+                <configuration>
+                    <source>${jdk.source}</source>
+                    <target>${jdk.target}</target>
+                    <encoding>ISO-8859-1</encoding>
+                    <debug>${jdk.debug}</debug>
+                    <optimize>${jdk.optimize}</optimize>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>${maven-jar-plugin.version}</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${maven-surefire-plugin.version}</version>
+                <configuration>
+                    <skipTests>${skipTests}</skipTests>
+                </configuration>
+            </plugin>
+
+
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>cobertura-maven-plugin</artifactId>
+                <version>${cobertura-maven-plugin.version}</version>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <version>${maven-antrun-plugin.version}</version>
+                <executions>
+                    <execution>
+                        <phase>validate</phase>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                        <configuration>
+                            <tasks>
+                                <echo>*******************************************************************</echo>
+                                <echo>*******************************************************************</echo>
+                                <echo>[project.name] : ${project.name}</echo>
+                                <echo>[project.basedir] : ${project.basedir}</echo>
+                                <echo>[project.version] : ${project.version}</echo>
+                                <echo>[project.artifactId] ${project.artifactId}</echo>
+                                <echo>[project.build.directory] ${project.build.directory}</echo>
+                                <echo>[jdk.source] : ${jdk.source}</echo>
+                                <echo>[jdk.target] : ${jdk.target}</echo>
+                                <echo>[jdk.debug] : ${jdk.debug}</echo>
+                                <echo>[jdk.optimize] : ${jdk.optimize}</echo>
+                                <echo>[source encoding]: ${project.build.sourceEncoding}</echo>
+                                <echo>[M2_HOME] : ${env.M2_HOME}</echo>
+                                <echo>[LocalRepository] : ${settings.localRepository}</echo>
+                                <echo>*******************************************************************</echo>
+                                <echo>*******************************************************************</echo>
+                            </tasks>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+        </plugins>
+      </pluginManagement>
+    </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/google/common/base/Preconditions.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/google/common/base/Preconditions.java b/docker-java/src/main/java/com/google/common/base/Preconditions.java
new file mode 100644
index 0000000..6a15fb4
--- /dev/null
+++ b/docker-java/src/main/java/com/google/common/base/Preconditions.java
@@ -0,0 +1,443 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed 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.google.common.base;
+
+
+import java.util.NoSuchElementException;
+
+/**
+ * Simple static methods to be called at the start of your own methods to verify
+ * correct arguments and state. This allows constructs such as
+ * <pre>
+ *     if (count <= 0) {
+ *       throw new IllegalArgumentException("must be positive: " + count);
+ *     }</pre>
+ *
+ * to be replaced with the more compact
+ * <pre>
+ *     checkArgument(count > 0, "must be positive: %s", count);</pre>
+ *
+ * Note that the sense of the expression is inverted; with {@code Preconditions}
+ * you declare what you expect to be <i>true</i>, just as you do with an
+ * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/assert.html">
+ * {@code assert}</a> or a JUnit {@code assertTrue} call.
+ *
+ * <p><b>Warning:</b> only the {@code "%s"} specifier is recognized as a
+ * placeholder in these messages, not the full range of {@link
+ * String#format(String, Object[])} specifiers.
+ *
+ * <p>Take care not to confuse precondition checking with other similar types
+ * of checks! Precondition exceptions -- including those provided here, but also
+ * {@link IndexOutOfBoundsException}, {@link NoSuchElementException}, {@link
+ * UnsupportedOperationException} and others -- are used to signal that the
+ * <i>calling method</i> has made an error. This tells the caller that it should
+ * not have invoked the method when it did, with the arguments it did, or
+ * perhaps ever. Postcondition or other invariant failures should not throw
+ * these types of exceptions.
+ *
+ * <p>See the Guava User Guide on <a href=
+ * "http://code.google.com/p/guava-libraries/wiki/PreconditionsExplained">
+ * using {@code Preconditions}</a>.
+ *
+ * @author Kevin Bourrillion
+ * @since 2.0 (imported from Google Collections Library)
+ */
+public final class Preconditions {
+    private Preconditions() {}
+
+    /**
+     * Ensures the truth of an expression involving one or more parameters to the
+     * calling method.
+     *
+     * @param expression a boolean expression
+     * @throws IllegalArgumentException if {@code expression} is false
+     */
+    public static void checkArgument(boolean expression) {
+        if (!expression) {
+            throw new IllegalArgumentException();
+        }
+    }
+
+    /**
+     * Ensures the truth of an expression involving one or more parameters to the
+     * calling method.
+     *
+     * @param expression a boolean expression
+     * @param errorMessage the exception message to use if the check fails; will
+     *     be converted to a string using {@link String#valueOf(Object)}
+     * @throws IllegalArgumentException if {@code expression} is false
+     */
+    public static void checkArgument(
+            boolean expression, Object errorMessage) {
+        if (!expression) {
+            throw new IllegalArgumentException(String.valueOf(errorMessage));
+        }
+    }
+
+    /**
+     * Ensures the truth of an expression involving one or more parameters to the
+     * calling method.
+     *
+     * @param expression a boolean expression
+     * @param errorMessageTemplate a template for the exception message should the
+     *     check fail. The message is formed by replacing each {@code %s}
+     *     placeholder in the template with an argument. These are matched by
+     *     position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
+     *     Unmatched arguments will be appended to the formatted message in square
+     *     braces. Unmatched placeholders will be left as-is.
+     * @param errorMessageArgs the arguments to be substituted into the message
+     *     template. Arguments are converted to strings using
+     *     {@link String#valueOf(Object)}.
+     * @throws IllegalArgumentException if {@code expression} is false
+     * @throws NullPointerException if the check fails and either {@code
+     *     errorMessageTemplate} or {@code errorMessageArgs} is null (don't let
+     *     this happen)
+     */
+    public static void checkArgument(boolean expression,
+                                     String errorMessageTemplate,
+                                     Object... errorMessageArgs) {
+        if (!expression) {
+            throw new IllegalArgumentException(
+                    format(errorMessageTemplate, errorMessageArgs));
+        }
+    }
+
+    /**
+     * Ensures the truth of an expression involving the state of the calling
+     * instance, but not involving any parameters to the calling method.
+     *
+     * @param expression a boolean expression
+     * @throws IllegalStateException if {@code expression} is false
+     */
+    public static void checkState(boolean expression) {
+        if (!expression) {
+            throw new IllegalStateException();
+        }
+    }
+
+    /**
+     * Ensures the truth of an expression involving the state of the calling
+     * instance, but not involving any parameters to the calling method.
+     *
+     * @param expression a boolean expression
+     * @param errorMessage the exception message to use if the check fails; will
+     *     be converted to a string using {@link String#valueOf(Object)}
+     * @throws IllegalStateException if {@code expression} is false
+     */
+    public static void checkState(
+            boolean expression, Object errorMessage) {
+        if (!expression) {
+            throw new IllegalStateException(String.valueOf(errorMessage));
+        }
+    }
+
+    /**
+     * Ensures the truth of an expression involving the state of the calling
+     * instance, but not involving any parameters to the calling method.
+     *
+     * @param expression a boolean expression
+     * @param errorMessageTemplate a template for the exception message should the
+     *     check fail. The message is formed by replacing each {@code %s}
+     *     placeholder in the template with an argument. These are matched by
+     *     position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
+     *     Unmatched arguments will be appended to the formatted message in square
+     *     braces. Unmatched placeholders will be left as-is.
+     * @param errorMessageArgs the arguments to be substituted into the message
+     *     template. Arguments are converted to strings using
+     *     {@link String#valueOf(Object)}.
+     * @throws IllegalStateException if {@code expression} is false
+     * @throws NullPointerException if the check fails and either {@code
+     *     errorMessageTemplate} or {@code errorMessageArgs} is null (don't let
+     *     this happen)
+     */
+    public static void checkState(boolean expression,
+                                  String errorMessageTemplate,
+                                  Object... errorMessageArgs) {
+        if (!expression) {
+            throw new IllegalStateException(
+                    format(errorMessageTemplate, errorMessageArgs));
+        }
+    }
+
+    /**
+     * Ensures that an object reference passed as a parameter to the calling
+     * method is not null.
+     *
+     * @param reference an object reference
+     * @return the non-null reference that was validated
+     * @throws NullPointerException if {@code reference} is null
+     */
+    public static <T> T checkNotNull(T reference) {
+        if (reference == null) {
+            throw new NullPointerException();
+        }
+        return reference;
+    }
+
+    /**
+     * Ensures that an object reference passed as a parameter to the calling
+     * method is not null.
+     *
+     * @param reference an object reference
+     * @param errorMessage the exception message to use if the check fails; will
+     *     be converted to a string using {@link String#valueOf(Object)}
+     * @return the non-null reference that was validated
+     * @throws NullPointerException if {@code reference} is null
+     */
+    public static <T> T checkNotNull(T reference, Object errorMessage) {
+        if (reference == null) {
+            throw new NullPointerException(String.valueOf(errorMessage));
+        }
+        return reference;
+    }
+
+    /**
+     * Ensures that an object reference passed as a parameter to the calling
+     * method is not null.
+     *
+     * @param reference an object reference
+     * @param errorMessageTemplate a template for the exception message should the
+     *     check fail. The message is formed by replacing each {@code %s}
+     *     placeholder in the template with an argument. These are matched by
+     *     position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
+     *     Unmatched arguments will be appended to the formatted message in square
+     *     braces. Unmatched placeholders will be left as-is.
+     * @param errorMessageArgs the arguments to be substituted into the message
+     *     template. Arguments are converted to strings using
+     *     {@link String#valueOf(Object)}.
+     * @return the non-null reference that was validated
+     * @throws NullPointerException if {@code reference} is null
+     */
+    public static <T> T checkNotNull(T reference,
+                                     String errorMessageTemplate,
+                                     Object... errorMessageArgs) {
+        if (reference == null) {
+            // If either of these parameters is null, the right thing happens anyway
+            throw new NullPointerException(
+                    format(errorMessageTemplate, errorMessageArgs));
+        }
+        return reference;
+    }
+
+  /*
+   * All recent hotspots (as of 2009) *really* like to have the natural code
+   *
+   * if (guardExpression) {
+   *    throw new BadException(messageExpression);
+   * }
+   *
+   * refactored so that messageExpression is moved to a separate
+   * String-returning method.
+   *
+   * if (guardExpression) {
+   *    throw new BadException(badMsg(...));
+   * }
+   *
+   * The alternative natural refactorings into void or Exception-returning
+   * methods are much slower.  This is a big deal - we're talking factors of
+   * 2-8 in microbenchmarks, not just 10-20%.  (This is a hotspot optimizer
+   * bug, which should be fixed, but that's a separate, big project).
+   *
+   * The coding pattern above is heavily used in java.util, e.g. in ArrayList.
+   * There is a RangeCheckMicroBenchmark in the JDK that was used to test this.
+   *
+   * But the methods in this class want to throw different exceptions,
+   * depending on the args, so it appears that this pattern is not directly
+   * applicable.  But we can use the ridiculous, devious trick of throwing an
+   * exception in the middle of the construction of another exception.
+   * Hotspot is fine with that.
+   */
+
+    /**
+     * Ensures that {@code index} specifies a valid <i>element</i> in an array,
+     * list or string of size {@code size}. An element index may range from zero,
+     * inclusive, to {@code size}, exclusive.
+     *
+     * @param index a user-supplied index identifying an element of an array, list
+     *     or string
+     * @param size the size of that array, list or string
+     * @return the value of {@code index}
+     * @throws IndexOutOfBoundsException if {@code index} is negative or is not
+     *     less than {@code size}
+     * @throws IllegalArgumentException if {@code size} is negative
+     */
+    public static int checkElementIndex(int index, int size) {
+        return checkElementIndex(index, size, "index");
+    }
+
+    /**
+     * Ensures that {@code index} specifies a valid <i>element</i> in an array,
+     * list or string of size {@code size}. An element index may range from zero,
+     * inclusive, to {@code size}, exclusive.
+     *
+     * @param index a user-supplied index identifying an element of an array, list
+     *     or string
+     * @param size the size of that array, list or string
+     * @param desc the text to use to describe this index in an error message
+     * @return the value of {@code index}
+     * @throws IndexOutOfBoundsException if {@code index} is negative or is not
+     *     less than {@code size}
+     * @throws IllegalArgumentException if {@code size} is negative
+     */
+    public static int checkElementIndex(
+            int index, int size, String desc) {
+        // Carefully optimized for execution by hotspot (explanatory comment above)
+        if (index < 0 || index >= size) {
+            throw new IndexOutOfBoundsException(badElementIndex(index, size, desc));
+        }
+        return index;
+    }
+
+    private static String badElementIndex(int index, int size, String desc) {
+        if (index < 0) {
+            return format("%s (%s) must not be negative", desc, index);
+        } else if (size < 0) {
+            throw new IllegalArgumentException("negative size: " + size);
+        } else { // index >= size
+            return format("%s (%s) must be less than size (%s)", desc, index, size);
+        }
+    }
+
+    /**
+     * Ensures that {@code index} specifies a valid <i>position</i> in an array,
+     * list or string of size {@code size}. A position index may range from zero
+     * to {@code size}, inclusive.
+     *
+     * @param index a user-supplied index identifying a position in an array, list
+     *     or string
+     * @param size the size of that array, list or string
+     * @return the value of {@code index}
+     * @throws IndexOutOfBoundsException if {@code index} is negative or is
+     *     greater than {@code size}
+     * @throws IllegalArgumentException if {@code size} is negative
+     */
+    public static int checkPositionIndex(int index, int size) {
+        return checkPositionIndex(index, size, "index");
+    }
+
+    /**
+     * Ensures that {@code index} specifies a valid <i>position</i> in an array,
+     * list or string of size {@code size}. A position index may range from zero
+     * to {@code size}, inclusive.
+     *
+     * @param index a user-supplied index identifying a position in an array, list
+     *     or string
+     * @param size the size of that array, list or string
+     * @param desc the text to use to describe this index in an error message
+     * @return the value of {@code index}
+     * @throws IndexOutOfBoundsException if {@code index} is negative or is
+     *     greater than {@code size}
+     * @throws IllegalArgumentException if {@code size} is negative
+     */
+    public static int checkPositionIndex(
+            int index, int size, String desc) {
+        // Carefully optimized for execution by hotspot (explanatory comment above)
+        if (index < 0 || index > size) {
+            throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc));
+        }
+        return index;
+    }
+
+    private static String badPositionIndex(int index, int size, String desc) {
+        if (index < 0) {
+            return format("%s (%s) must not be negative", desc, index);
+        } else if (size < 0) {
+            throw new IllegalArgumentException("negative size: " + size);
+        } else { // index > size
+            return format("%s (%s) must not be greater than size (%s)",
+                    desc, index, size);
+        }
+    }
+
+    /**
+     * Ensures that {@code start} and {@code end} specify a valid <i>positions</i>
+     * in an array, list or string of size {@code size}, and are in order. A
+     * position index may range from zero to {@code size}, inclusive.
+     *
+     * @param start a user-supplied index identifying a starting position in an
+     *     array, list or string
+     * @param end a user-supplied index identifying a ending position in an array,
+     *     list or string
+     * @param size the size of that array, list or string
+     * @throws IndexOutOfBoundsException if either index is negative or is
+     *     greater than {@code size}, or if {@code end} is less than {@code start}
+     * @throws IllegalArgumentException if {@code size} is negative
+     */
+    public static void checkPositionIndexes(int start, int end, int size) {
+        // Carefully optimized for execution by hotspot (explanatory comment above)
+        if (start < 0 || end < start || end > size) {
+            throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size));
+        }
+    }
+
+    private static String badPositionIndexes(int start, int end, int size) {
+        if (start < 0 || start > size) {
+            return badPositionIndex(start, size, "start index");
+        }
+        if (end < 0 || end > size) {
+            return badPositionIndex(end, size, "end index");
+        }
+        // end < start
+        return format("end index (%s) must not be less than start index (%s)",
+                end, start);
+    }
+
+    /**
+     * Substitutes each {@code %s} in {@code template} with an argument. These
+     * are matched by position - the first {@code %s} gets {@code args[0]}, etc.
+     * If there are more arguments than placeholders, the unmatched arguments will
+     * be appended to the end of the formatted message in square braces.
+     *
+     * @param template a non-null string containing 0 or more {@code %s}
+     *     placeholders.
+     * @param args the arguments to be substituted into the message
+     *     template. Arguments are converted to strings using
+     *     {@link String#valueOf(Object)}. Arguments can be null.
+     */
+    static String format(String template, Object... args) {
+        template = String.valueOf(template); // null -> "null"
+
+        // start substituting the arguments into the '%s' placeholders
+        StringBuilder builder = new StringBuilder(
+                template.length() + 16 * args.length);
+        int templateStart = 0;
+        int i = 0;
+        while (i < args.length) {
+            int placeholderStart = template.indexOf("%s", templateStart);
+            if (placeholderStart == -1) {
+                break;
+            }
+            builder.append(template.substring(templateStart, placeholderStart));
+            builder.append(args[i++]);
+            templateStart = placeholderStart + 2;
+        }
+        builder.append(template.substring(templateStart));
+
+        // if we run out of placeholders, append the extra args in square braces
+        if (i < args.length) {
+            builder.append(" [");
+            builder.append(args[i++]);
+            while (i < args.length) {
+                builder.append(", ");
+                builder.append(args[i++]);
+            }
+            builder.append(']');
+        }
+
+        return builder.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/DockerClient.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/DockerClient.java b/docker-java/src/main/java/com/kpelykh/docker/client/DockerClient.java
new file mode 100644
index 0000000..d29d28e
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/DockerClient.java
@@ -0,0 +1,767 @@
+package com.kpelykh.docker.client;
+
+import com.google.common.base.Preconditions;
+import com.kpelykh.docker.client.model.*;
+import com.kpelykh.docker.client.utils.CompressArchiveUtil;
+import com.kpelykh.docker.client.utils.JsonClientFilter;
+import com.sun.jersey.api.client.*;
+import com.sun.jersey.api.client.WebResource.Builder;
+import com.sun.jersey.api.client.config.ClientConfig;
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.api.client.filter.LoggingFilter;
+import com.sun.jersey.api.json.JSONConfiguration;
+import com.sun.jersey.client.apache4.ApacheHttpClient4;
+import com.sun.jersey.client.apache4.ApacheHttpClient4Handler;
+import com.sun.jersey.core.util.MultivaluedMapImpl;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.client.HttpClient;
+import org.apache.http.conn.scheme.PlainSocketFactory;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.conn.PoolingClientConnectionManager;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ *
+ * @author Konstantin Pelykh (kpelykh@gmail.com)
+ *
+ */
+public class DockerClient
+{
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(DockerClient.class);
+
+    private static DockerClient instance;
+    private Client client;
+    private String restEndpointUrl;
+
+    public DockerClient(String serverUrl) {
+        restEndpointUrl = serverUrl + "/v1.8";
+        ClientConfig clientConfig = new DefaultClientConfig();
+        clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
+
+        SchemeRegistry schemeRegistry = new SchemeRegistry();
+        schemeRegistry.register(new Scheme("http", 4243, PlainSocketFactory.getSocketFactory()));
+
+        PoolingClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry);
+        // Increase max total connection
+        cm.setMaxTotal(1000);
+        // Increase default max connection per route
+        cm.setDefaultMaxPerRoute(1000);
+
+        HttpClient httpClient = new DefaultHttpClient(cm);
+        client = new ApacheHttpClient4(new ApacheHttpClient4Handler(httpClient, null, false), clientConfig);
+
+        //Experimental support for unix sockets:
+        //client = new UnixSocketClient(clientConfig);
+
+        client.addFilter(new JsonClientFilter());        
+        client.addFilter(new LoggingFilter());
+    }
+
+    /**
+     ** MISC API
+     **
+     **/
+
+    public Info info() throws DockerException {
+        WebResource webResource = client.resource(restEndpointUrl + "/info");
+
+        try {
+            LOGGER.trace("GET: {}", webResource);
+            return webResource.accept(MediaType.APPLICATION_JSON).get(Info.class);
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error.", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+    }
+
+
+    public Version version() throws DockerException {
+        WebResource webResource = client.resource(restEndpointUrl + "/version");
+
+        try {
+            LOGGER.trace("GET: {}", webResource);
+            return webResource.accept(MediaType.APPLICATION_JSON).get(Version.class);
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error.", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+    }
+
+
+    /**
+     ** IMAGE API
+     **
+     **/
+
+    public ClientResponse pull(String repository) throws DockerException {
+        return this.pull(repository, null, null);
+    }
+
+    public ClientResponse pull(String repository, String tag) throws DockerException {
+        return this.pull(repository, tag, null);
+    }
+
+    public ClientResponse pull(String repository, String tag, String registry) throws DockerException {
+        Preconditions.checkNotNull(repository, "Repository was not specified");
+
+        if (StringUtils.countMatches(repository, ":") == 1) {
+            String repositoryTag[] = StringUtils.split(repository);
+            repository = repositoryTag[0];
+            tag = repositoryTag[1];
+
+        }
+
+        MultivaluedMap<String,String> params = new MultivaluedMapImpl();
+        params.add("tag", tag);
+        params.add("fromImage", repository);
+        params.add("registry", registry);
+
+        WebResource webResource = client.resource(restEndpointUrl + "/images/create").queryParams(params);
+
+        try {
+            LOGGER.trace("POST: {}", webResource);
+            return webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).post(ClientResponse.class);
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error.", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+    }
+
+    /**
+     * Create an image by importing the given stream of a tar file.
+     *
+     * @param repository the repository to import to
+     * @param tag any tag for this image
+     * @param imageStream the InputStream of the tar file
+     * @return an {@link ImageCreateResponse} containing the id of the imported image
+     * @throws DockerException if the import fails for some reason.
+     */
+    public ImageCreateResponse importImage(String repository, String tag, InputStream imageStream) throws DockerException {
+        Preconditions.checkNotNull(repository, "Repository was not specified");
+        Preconditions.checkNotNull(imageStream, "imageStream was not provided");
+
+        MultivaluedMap<String,String> params = new MultivaluedMapImpl();
+        params.add("repo", repository);
+        params.add("tag", tag);
+        params.add("fromSrc","-");
+
+        WebResource webResource = client.resource(restEndpointUrl + "/images/create").queryParams(params);
+
+        try {
+            LOGGER.trace("POST: {}", webResource);
+            return webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).post(ImageCreateResponse.class,imageStream);
+
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error.", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+    }
+
+    public List<SearchItem> search(String search) throws DockerException {
+        WebResource webResource = client.resource(restEndpointUrl + "/images/search").queryParam("term", search);
+        try {
+            return webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType<List<SearchItem>>() {});
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error.", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+
+    }
+
+    public void removeImage(String imageId) throws DockerException {
+        Preconditions.checkState(!StringUtils.isEmpty(imageId), "Image ID can't be empty");
+
+        try {
+            WebResource webResource = client.resource(restEndpointUrl + "/images/" + imageId);
+            LOGGER.trace("DELETE: {}", webResource);
+            webResource.delete();
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 204) {
+                //no error
+                LOGGER.trace("Successfully removed image " + imageId);
+            } else if (exception.getResponse().getStatus() == 404) {
+                LOGGER.warn("{} no such image", imageId);
+            } else if (exception.getResponse().getStatus() == 409) {
+                throw new DockerException("Conflict");
+            } else if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error.", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+
+    }
+
+    public void removeImages(List<String> images) throws DockerException {
+        Preconditions.checkNotNull(images, "List of images can't be null");
+
+        for (String imageId : images) {
+            removeImage(imageId);
+        }
+    }
+
+    public String getVizImages() throws DockerException {
+        WebResource webResource = client.resource(restEndpointUrl + "/images/viz");
+
+        try {
+            LOGGER.trace("GET: {}", webResource);
+            String response = webResource.get(String.class);
+            LOGGER.trace("Response: {}", response);
+
+            return response;
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 400) {
+                throw new DockerException("bad parameter");
+            } else if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+    }
+
+
+    public List<Image> getImages() throws DockerException {
+        return this.getImages(null, false);
+    }
+
+    public List<Image> getImages(boolean allContainers) throws DockerException {
+        return this.getImages(null, allContainers);
+    }
+
+    public List<Image> getImages(String name) throws DockerException {
+        return this.getImages(name, false);
+    }
+
+    public List<Image> getImages(String name, boolean allImages) throws DockerException {
+
+        MultivaluedMap<String,String> params = new MultivaluedMapImpl();
+        params.add("filter", name);
+        params.add("all", allImages ? "1" : "0");
+
+        WebResource webResource = client.resource(restEndpointUrl + "/images/json").queryParams(params);
+
+        try {
+            LOGGER.trace("GET: {}", webResource);
+            List<Image> images = webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType<List<Image>>() {});
+            LOGGER.trace("Response: {}", images);
+            return images;
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 400) {
+                throw new DockerException("bad parameter");
+            } else if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error", exception);
+            } else {
+                throw new DockerException();
+            }
+        }
+
+    }
+
+    public ImageInspectResponse inspectImage(String imageId) throws DockerException, NotFoundException {
+
+        WebResource webResource = client.resource(restEndpointUrl + String.format("/images/%s/json", imageId));
+
+        try {
+            LOGGER.trace("GET: {}", webResource);
+            return webResource.accept(MediaType.APPLICATION_JSON).get(ImageInspectResponse.class);
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 404) {
+                throw new NotFoundException(String.format("No such image %s", imageId));
+            } else if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+    }
+
+    /**
+     ** CONTAINER API
+     **
+     **/
+
+    public List<Container> listContainers(boolean allContainers) {
+        return this.listContainers(allContainers, false, -1, false, null, null);
+    }
+
+    public List<Container> listContainers(boolean allContainers, boolean latest) {
+        return this.listContainers(allContainers, latest, -1, false, null, null);
+    }
+
+    public List<Container> listContainers(boolean allContainers, boolean latest, int limit) {
+        return this.listContainers(allContainers, latest, limit, false, null, null);
+    }
+
+    public List<Container> listContainers(boolean allContainers, boolean latest, int limit, boolean showSize) {
+        return this.listContainers(allContainers, latest, limit, showSize, null, null);
+    }
+
+    public List<Container> listContainers(boolean allContainers, boolean latest, int limit, boolean showSize, String since) {
+        return this.listContainers(allContainers, latest, limit, false, since, null);
+    }
+
+    public List<Container> listContainers(boolean allContainers, boolean latest, int limit, boolean showSize, String since, String before) {
+
+        MultivaluedMap<String,String> params = new MultivaluedMapImpl();
+        params.add("limit", latest ? "1" : String.valueOf(limit));
+        params.add("all", allContainers ? "1" : "0");
+        params.add("since", since);
+        params.add("before", before);
+        params.add("size", showSize ? "1" : "0");
+
+        WebResource webResource = client.resource(restEndpointUrl + "/containers/json").queryParams(params);
+        LOGGER.trace("GET: {}", webResource);
+        List<Container> containers = webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType<List<Container>>() {});
+        LOGGER.trace("Response: {}", containers);
+
+        return containers;
+    }
+
+    public ContainerCreateResponse createContainer(ContainerConfig config) throws DockerException{
+        return createContainer(config, null);
+    }
+
+    public ContainerCreateResponse createContainer(ContainerConfig config,String name) throws DockerException, NotFoundException {
+
+        MultivaluedMap<String,String> params = new MultivaluedMapImpl();
+        if(name != null){
+            params.add("name", name);
+        }
+        WebResource webResource = client.resource(restEndpointUrl + "/containers/create").queryParams(params);
+
+        try {
+            LOGGER.trace("POST: {} ", webResource);
+            return webResource.accept(MediaType.APPLICATION_JSON)
+                    .type(MediaType.APPLICATION_JSON)
+                    .post(ContainerCreateResponse.class, config);
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 404) {
+                throw new NotFoundException(String.format("%s is an unrecognized image. Please pull the image first.", config.getImage()));
+            } else if (exception.getResponse().getStatus() == 406) {
+                throw new DockerException("impossible to attach (container not running)");
+            } else if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+
+    }
+
+    public void startContainer(String containerId) throws DockerException {
+        this.startContainer(containerId, null);
+    }
+
+    public void startContainer(String containerId, HostConfig hostConfig) throws DockerException, NotFoundException {
+
+        WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/start", containerId));
+
+        try {
+            LOGGER.trace("POST: {}", webResource);
+            Builder builder = webResource.accept(MediaType.TEXT_PLAIN);
+            if (hostConfig != null) {
+                builder.type(MediaType.APPLICATION_JSON).post(hostConfig);
+            } else {
+                builder.post((HostConfig) null);
+            }
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 404) {
+                throw new NotFoundException(String.format("No such container %s", containerId));
+            } else if (exception.getResponse().getStatus() == 204) {
+                //no error
+                LOGGER.trace("Successfully started container {}", containerId);
+            } else if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+    }
+
+    public ContainerInspectResponse inspectContainer(String containerId) throws DockerException, NotFoundException {
+
+        WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/json", containerId));
+
+        try {
+            LOGGER.trace("GET: {}", webResource);
+            return webResource.accept(MediaType.APPLICATION_JSON).get(ContainerInspectResponse.class);
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 404) {
+                throw new NotFoundException(String.format("No such container %s", containerId));
+            } else if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+    }
+
+
+    public void removeContainer(String container) throws DockerException {
+        this.removeContainer(container, false);
+    }
+
+    public void removeContainer(String containerId, boolean removeVolumes) throws DockerException {
+        Preconditions.checkState(!StringUtils.isEmpty(containerId), "Container ID can't be empty");
+
+        WebResource webResource = client.resource(restEndpointUrl + "/containers/" + containerId).queryParam("v", removeVolumes ? "1" : "0");
+
+        try {
+            LOGGER.trace("DELETE: {}", webResource);
+            String response = webResource.accept(MediaType.APPLICATION_JSON).delete(String.class);
+            LOGGER.trace("Response: {}", response);
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 204) {
+                //no error
+                LOGGER.trace("Successfully removed container " + containerId);
+            } else if (exception.getResponse().getStatus() == 400) {
+                throw new DockerException("bad parameter");
+            } else if (exception.getResponse().getStatus() == 404) {
+                // should really throw a NotFoundException instead of silently ignoring the problem
+                LOGGER.warn(String.format("%s is an unrecognized container.", containerId));
+            } else if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+    }
+
+
+    public void removeContainers(List<String> containers, boolean removeVolumes) throws DockerException {
+        Preconditions.checkNotNull(containers, "List of containers can't be null");
+
+        for (String containerId : containers) {
+            removeContainer(containerId, removeVolumes);
+        }
+    }
+
+    public int waitContainer(String containerId) throws DockerException, NotFoundException {
+        WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/wait", containerId));
+
+        try {
+            LOGGER.trace("POST: {}", webResource);
+            JSONObject jsonObject = webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post(JSONObject.class);
+            return jsonObject.getInt("StatusCode");
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 404) {
+                throw new NotFoundException(String.format("No such container %s", containerId));
+            } else if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        } catch (JSONException e) {
+            throw new DockerException(e);
+        }
+    }
+
+
+    public ClientResponse logContainer(String containerId) throws DockerException {
+        return logContainer(containerId, false);
+    }
+
+    public ClientResponse logContainerStream(String containerId) throws DockerException {
+        return logContainer(containerId, true);
+    }
+
+    private ClientResponse logContainer(String containerId, boolean stream) throws DockerException, NotFoundException {
+        MultivaluedMap<String,String> params = new MultivaluedMapImpl();
+        params.add("logs", "1");
+        params.add("stdout", "1");
+        params.add("stderr", "1");
+        if (stream) {
+            params.add("stream", "1"); // this parameter keeps stream open indefinitely
+        }
+
+        WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/attach", containerId))
+                .queryParams(params);
+
+        try {
+            LOGGER.trace("POST: {}", webResource);
+            return webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).post(ClientResponse.class, params);
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 400) {
+                throw new DockerException("bad parameter");
+            } else if (exception.getResponse().getStatus() == 404) {
+                throw new NotFoundException(String.format("No such container %s", containerId));
+            } else if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+    }
+
+    public ClientResponse copyFile(String containerId, String resource) throws DockerException {
+        CopyConfig copyConfig = new CopyConfig();
+        copyConfig.setResource(resource);
+
+        WebResource webResource =
+            client.resource(restEndpointUrl + String.format("/containers/%s/copy", containerId));
+
+        try {
+            LOGGER.trace("POST: " + webResource.toString());
+            WebResource.Builder builder =
+                webResource.accept(MediaType.APPLICATION_OCTET_STREAM_TYPE).type("application/json");
+
+            return builder.post(ClientResponse.class, copyConfig.toString());
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 400) {
+                throw new DockerException("bad parameter");
+            } else if (exception.getResponse().getStatus() == 404) {
+                throw new DockerException(String.format("No such container %s", containerId));
+            } else if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+    }
+
+    public List<ChangeLog> containterDiff(String containerId) throws DockerException, NotFoundException {
+
+        WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/changes", containerId));
+
+        try {
+            LOGGER.trace("GET: {}", webResource);
+            return webResource.accept(MediaType.APPLICATION_JSON).get(new GenericType<List<ChangeLog>>() {});
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 404) {
+                throw new NotFoundException(String.format("No such container %s", containerId));
+            } else if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+    }
+
+
+
+
+    public void stopContainer(String containerId) throws DockerException {
+        this.stopContainer(containerId, 10);
+    }
+
+    public void stopContainer(String containerId, int timeout) throws DockerException {
+
+        WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/stop", containerId))
+                .queryParam("t", String.valueOf(timeout));
+
+
+        try {
+            LOGGER.trace("POST: {}", webResource);
+            webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post();
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 404) {
+                LOGGER.warn("No such container {}", containerId);
+            } else if (exception.getResponse().getStatus() == 204) {
+                //no error
+                LOGGER.trace("Successfully stopped container {}", containerId);
+            } else if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+    }
+
+    public void kill(String containerId) throws DockerException {
+        WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/kill", containerId));
+
+        try {
+            LOGGER.trace("POST: {}", webResource);
+            webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post();
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 404) {
+                LOGGER.warn("No such container {}", containerId);
+            } else if (exception.getResponse().getStatus() == 204) {
+                //no error
+                LOGGER.trace("Successfully killed container {}", containerId);
+            } else if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+    }
+
+    public void restart(String containerId, int timeout) throws DockerException, NotFoundException {
+        WebResource webResource = client.resource(restEndpointUrl + String.format("/containers/%s/restart", containerId));
+
+        try {
+            LOGGER.trace("POST: {}", webResource);
+            webResource.accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON).post();
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 404) {
+                throw new NotFoundException(String.format("No such container %s", containerId));
+            } else if (exception.getResponse().getStatus() == 204) {
+                //no error
+                LOGGER.trace("Successfully restarted container {}", containerId);
+            } else if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        }
+    }
+
+    public String commit(CommitConfig commitConfig) throws DockerException, NotFoundException {
+        Preconditions.checkNotNull(commitConfig.getContainer(), "Container ID was not specified");
+
+        MultivaluedMap<String,String> params = new MultivaluedMapImpl();
+        params.add("container", commitConfig.getContainer());
+        params.add("repo", commitConfig.getRepo());
+        params.add("tag", commitConfig.getTag());
+        params.add("m", commitConfig.getMessage());
+        params.add("author", commitConfig.getAuthor());
+        params.add("run", commitConfig.getRun());
+
+        WebResource webResource = client.resource(restEndpointUrl + "/commit").queryParams(params);
+
+        try {
+            LOGGER.trace("POST: {}", webResource);
+            JSONObject jsonObject = webResource.accept("application/vnd.docker.raw-stream").post(JSONObject.class, params);
+            return jsonObject.getString("Id");
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 404) {
+                throw new NotFoundException(String.format("No such container %s", commitConfig.getContainer()));
+            } else if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        } catch (JSONException e) {
+            throw new DockerException(e);
+        }
+    }
+
+
+    public ClientResponse build(File dockerFolder) throws DockerException {
+        return this.build(dockerFolder, null);
+    }
+    
+    public ClientResponse build(File dockerFolder, String tag) throws DockerException {
+    	return this.build(dockerFolder, null, false);
+    }
+
+    public ClientResponse build(File dockerFolder, String tag, boolean noCache) throws DockerException {
+        Preconditions.checkNotNull(dockerFolder, "Folder is null");
+        Preconditions.checkArgument(dockerFolder.exists(), "Folder %s doesn't exist", dockerFolder);
+        Preconditions.checkState(new File(dockerFolder, "Dockerfile").exists(), "Dockerfile doesn't exist in " + dockerFolder);
+
+        //We need to use Jersey HttpClient here, since ApacheHttpClient4 will not add boundary filed to
+        //Content-Type: multipart/form-data; boundary=Boundary_1_372491238_1372806136625
+
+        MultivaluedMap<String,String> params = new MultivaluedMapImpl();
+        params.add("t", tag);
+        if(noCache) {
+        	params.add("nocache", "true");
+        }
+
+        // ARCHIVE TAR
+        String archiveNameWithOutExtension = UUID.randomUUID().toString();
+
+        File dockerFolderTar = null;
+        File tmpDockerContextFolder = null;
+
+        try {
+            File dockerFile = new File(dockerFolder, "Dockerfile");
+            List<String> dockerFileContent = FileUtils.readLines(dockerFile);
+
+            if (dockerFileContent.size() <= 0) {
+                throw new DockerException(String.format("Dockerfile %s is empty", dockerFile));
+            }
+
+            //Create tmp docker context folder
+            tmpDockerContextFolder = new File(FileUtils.getTempDirectoryPath(), "docker-java-build" + archiveNameWithOutExtension);
+
+            FileUtils.copyFileToDirectory(dockerFile, tmpDockerContextFolder);
+
+            for (String cmd : dockerFileContent) {
+                if (StringUtils.startsWithIgnoreCase(cmd.trim(), "ADD ")) {
+                    String addArgs[] = StringUtils.split(cmd, " \t");
+                    if (addArgs.length != 3) {
+                        throw new DockerException(String.format("Wrong format on line [%s]", cmd));
+                    }
+
+                    File src = new File(addArgs[1]);
+                    if (!src.isAbsolute()) {
+                        src = new File(dockerFolder, addArgs[1]).getCanonicalFile();
+                    }
+
+                    if (!src.exists()) {
+                        throw new DockerException(String.format("Source file %s doesnt' exist", src));
+                    }
+                    if (src.isDirectory()) {
+                        FileUtils.copyDirectory(src, tmpDockerContextFolder);
+                    } else {
+                        FileUtils.copyFileToDirectory(src, tmpDockerContextFolder);
+                    }
+                }
+            }
+
+            dockerFolderTar = CompressArchiveUtil.archiveTARFiles(tmpDockerContextFolder, archiveNameWithOutExtension);
+
+        } catch (IOException ex) {
+            FileUtils.deleteQuietly(dockerFolderTar);
+            FileUtils.deleteQuietly(tmpDockerContextFolder);
+            throw new DockerException("Error occurred while preparing Docker context folder.", ex);
+        }
+
+        WebResource webResource = client.resource(restEndpointUrl + "/build").queryParams(params);
+
+        try {
+            LOGGER.trace("POST: {}", webResource);
+            return webResource
+                    .type("application/tar")
+                    .accept(MediaType.TEXT_PLAIN)
+                    .post(ClientResponse.class, FileUtils.openInputStream(dockerFolderTar));
+        } catch (UniformInterfaceException exception) {
+            if (exception.getResponse().getStatus() == 500) {
+                throw new DockerException("Server error", exception);
+            } else {
+                throw new DockerException(exception);
+            }
+        } catch (IOException e) {
+            throw new DockerException(e);
+        } finally {
+            FileUtils.deleteQuietly(dockerFolderTar);
+            FileUtils.deleteQuietly(tmpDockerContextFolder);
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/DockerException.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/DockerException.java b/docker-java/src/main/java/com/kpelykh/docker/client/DockerException.java
new file mode 100644
index 0000000..aa3df66
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/DockerException.java
@@ -0,0 +1,25 @@
+package com.kpelykh.docker.client;
+
+/**
+ *
+ * @author Konstantin Pelykh (kpelykh@gmail.com)
+ *
+ */
+
+public class DockerException extends Exception {
+
+    public DockerException() {
+    }
+
+    public DockerException(String message) {
+        super(message);
+    }
+
+    public DockerException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public DockerException(Throwable cause) {
+        super(cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/NotFoundException.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/NotFoundException.java b/docker-java/src/main/java/com/kpelykh/docker/client/NotFoundException.java
new file mode 100644
index 0000000..f6c8fe5
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/NotFoundException.java
@@ -0,0 +1,20 @@
+package com.kpelykh.docker.client;
+
+/**
+ * Indicates that the given entity does not exist.
+ *
+ * @author Ryan Campbell ryan.campbell@gmail.com
+ */
+public class NotFoundException extends DockerException {
+    public NotFoundException() {
+
+    }
+
+    public NotFoundException(String message) {
+        super(message);
+    }
+
+    public NotFoundException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/UnixSocketClient.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/UnixSocketClient.java b/docker-java/src/main/java/com/kpelykh/docker/client/UnixSocketClient.java
new file mode 100644
index 0000000..7558203
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/UnixSocketClient.java
@@ -0,0 +1,12 @@
+package com.kpelykh.docker.client;
+
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.config.ClientConfig;
+
+
+public class UnixSocketClient extends Client {
+
+  public UnixSocketClient(ClientConfig clientConfig) {
+    super(new UnixSocketClientHandler(), clientConfig);
+  }
+}


[7/7] git commit: updated refs/heads/docker to 2ab7524

Posted by tu...@apache.org.
changes to add a docker host


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/2ab75245
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/2ab75245
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/2ab75245

Branch: refs/heads/docker
Commit: 2ab75245deef1ee115654e495eaec2413977f05b
Parents: 0182151
Author: tuna <ng...@gmail.com>
Authored: Mon Mar 31 00:56:48 2014 +0700
Committer: tuna <ng...@gmail.com>
Committed: Mon Mar 31 00:56:48 2014 +0700

----------------------------------------------------------------------
 agent/bindir/cloud-setup-agent.in               |   4 +
 .../command/admin/cluster/AddClusterCmd.java    |   2 +-
 .../user/template/RegisterTemplateCmd.java      |   2 +-
 plugins/hypervisors/docker/pom.xml              |  14 +-
 .../docker/resource/DockerResource.java         | 150 +++++++-------
 plugins/pom.xml                                 |   1 +
 python/lib/cloudutils/globalEnv.py              |   2 +
 python/lib/cloudutils/serviceConfig.py          |  20 +-
 .../kvm/discoverer/DockerServerDiscoverer.java  | 200 +++++++++++++++++++
 .../template/HypervisorTemplateAdapter.java     |  23 +--
 .../com/cloud/template/TemplateAdapterBase.java |   9 +-
 11 files changed, 328 insertions(+), 99 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ab75245/agent/bindir/cloud-setup-agent.in
----------------------------------------------------------------------
diff --git a/agent/bindir/cloud-setup-agent.in b/agent/bindir/cloud-setup-agent.in
index 6932672..667d130 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()

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ab75245/api/src/org/apache/cloudstack/api/command/admin/cluster/AddClusterCmd.java
----------------------------------------------------------------------
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 e8cb10b..92928ae 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")

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ab75245/api/src/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java
----------------------------------------------------------------------
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 bba90bf..afdbbb9 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")

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ab75245/plugins/hypervisors/docker/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/docker/pom.xml b/plugins/hypervisors/docker/pom.xml
index 4ede673..1f7a430 100755
--- a/plugins/hypervisors/docker/pom.xml
+++ b/plugins/hypervisors/docker/pom.xml
@@ -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>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ab75245/plugins/hypervisors/docker/src/com/cloud/hypervisor/docker/resource/DockerResource.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 501df0d..6c11e9a 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<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
-		
-	}
-
-	@Override
-	public Map<String, Object> getConfigParams() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public int getRunLevel() {
-		// TODO Auto-generated method stub
-		return 0;
-	}
-
-	@Override
-	public void setRunLevel(int level) {
-		// TODO Auto-generated method stub
-		
-	}
-
-	@Override
-	public Type getType() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public StartupCommand[] initialize() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public PingCommand getCurrentStatus(long id) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	protected String getDefaultScriptsDir() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-	
+    }
+
+    protected Answer execute(StopCommand cmd) {
+        return null;
+    }
+
+    private Answer execute(RebootCommand cmd) {
+        return null;
+    }
+
+    protected StartAnswer execute(StartCommand cmd) {
+        return null;
+    }
+
+    @Override
+    public Map<String, Object> getConfigParams() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public int getRunLevel() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void setConfigParams(Map<String, Object> arg0) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void setName(String arg0) {
+        // TODO Auto-generated method stub
+    }
+
+    @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;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ab75245/plugins/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/pom.xml b/plugins/pom.xml
index 86308bc..86a7ba8 100755
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -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>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ab75245/python/lib/cloudutils/globalEnv.py
----------------------------------------------------------------------
diff --git a/python/lib/cloudutils/globalEnv.py b/python/lib/cloudutils/globalEnv.py
index 867aa17..9f20212 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

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ab75245/python/lib/cloudutils/serviceConfig.py
----------------------------------------------------------------------
diff --git a/python/lib/cloudutils/serviceConfig.py b/python/lib/cloudutils/serviceConfig.py
index d7c7e78..7c5c32b 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")

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ab75245/server/src/com/cloud/hypervisor/kvm/discoverer/DockerServerDiscoverer.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/hypervisor/kvm/discoverer/DockerServerDiscoverer.java b/server/src/com/cloud/hypervisor/kvm/discoverer/DockerServerDiscoverer.java
index d7ce7c2..7b031d5 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<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;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ab75245/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 32f1287..7659b62 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;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/2ab75245/server/src/com/cloud/template/TemplateAdapterBase.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/template/TemplateAdapterBase.java b/server/src/com/cloud/template/TemplateAdapterBase.java
index c75c1e4..510be910 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


[3/7] add docker client

Posted by tu...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java b/docker-java/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java
new file mode 100644
index 0000000..6ce3f1c
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/UnixSocketClientHandler.java
@@ -0,0 +1,213 @@
+package com.kpelykh.docker.client;
+
+import com.sun.jersey.api.client.*;
+import com.sun.jersey.api.client.config.ClientConfig;
+import com.sun.jersey.core.header.InBoundHeaders;
+import com.sun.jersey.core.util.ReaderWriter;
+import jnr.unixsocket.UnixSocketAddress;
+import jnr.unixsocket.UnixSocketChannel;
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpException;
+import org.apache.http.HttpResponse;
+import org.apache.http.annotation.NotThreadSafe;
+import org.apache.http.client.methods.*;
+import org.apache.http.entity.AbstractHttpEntity;
+import org.apache.http.entity.BufferedHttpEntity;
+import org.apache.http.impl.DefaultHttpResponseFactory;
+import org.apache.http.impl.io.DefaultHttpResponseParser;
+import org.apache.http.impl.io.HttpRequestWriter;
+import org.apache.http.message.BasicLineFormatter;
+import org.apache.http.message.BasicLineParser;
+import org.apache.http.params.BasicHttpParams;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.net.URI;
+import java.nio.channels.Channels;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * TODO: Make thread-safe.
+ */
+@NotThreadSafe
+public class UnixSocketClientHandler extends RequestWriter implements ClientHandler {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(UnixSocketClientHandler.class);
+
+  public static final int BUFFERSIZE = 1024;
+  public static final String DOCKER_SOCKET_PATH = "/var/run/docker.sock";
+
+  @Override
+  public ClientResponse handle(ClientRequest cr) throws ClientHandlerException {
+    try {
+      File path = new File(DOCKER_SOCKET_PATH);
+      UnixSocketAddress address = new UnixSocketAddress(path);
+      UnixSocketChannel channel = UnixSocketChannel.open(address);
+      OutputStream unixSocketChannelOutputStream = Channels.newOutputStream(channel);
+
+      final HttpUriRequest request = getUriHttpRequest(cr);
+      BasicHttpParams params = new BasicHttpParams();
+
+      UnixSocketSessionOutputBuffer outputBuffer = new UnixSocketSessionOutputBuffer();
+      outputBuffer.init(unixSocketChannelOutputStream, BUFFERSIZE, params);
+      HttpRequestWriter writer = new HttpRequestWriter(outputBuffer, new BasicLineFormatter(), params);
+      writer.write(request);
+      outputBuffer.flush();
+
+      UnixSocketSessionInputBuffer inputBuffer = new UnixSocketSessionInputBuffer();
+      inputBuffer.init(Channels.newInputStream(channel), BUFFERSIZE, params);
+
+      HttpResponse response = new DefaultHttpResponseParser(inputBuffer, new BasicLineParser(), new DefaultHttpResponseFactory(), params).parse();
+      LOGGER.trace(response.toString());
+
+      ClientResponse clientResponse = new ClientResponse(response.getStatusLine().getStatusCode(),
+        getInBoundHeaders(response),
+        new HttpClientResponseInputStream(response),
+        getMessageBodyWorkers());
+
+      clientResponse.bufferEntity();
+      clientResponse.close();
+
+      return clientResponse;
+
+    } catch (IOException e) {
+      e.printStackTrace();
+    } catch (HttpException e) {
+      e.printStackTrace();
+    }
+    return null;
+  }
+
+  private HttpUriRequest getUriHttpRequest(final ClientRequest cr) {
+    final String strMethod = cr.getMethod();
+    final URI uri = cr.getURI();
+
+    final HttpEntity entity = getHttpEntity(cr);
+    final HttpUriRequest request;
+
+    if (strMethod.equals("GET")) {
+      request = new HttpGet(uri);
+    } else if (strMethod.equals("POST")) {
+      request = new HttpPost(uri);
+    } else if (strMethod.equals("PUT")) {
+      request = new HttpPut(uri);
+    } else if (strMethod.equals("DELETE")) {
+      request = new HttpDelete(uri);
+    } else if (strMethod.equals("HEAD")) {
+      request = new HttpHead(uri);
+    } else if (strMethod.equals("OPTIONS")) {
+      request = new HttpOptions(uri);
+    } else {
+      request = new HttpEntityEnclosingRequestBase() {
+        @Override
+        public String getMethod() {
+          return strMethod;
+        }
+
+        @Override
+        public URI getURI() {
+          return uri;
+        }
+      };
+    }
+
+    if (entity != null && request instanceof HttpEntityEnclosingRequestBase) {
+      ((HttpEntityEnclosingRequestBase) request).setEntity(entity);
+    } else if (entity != null) {
+      throw new ClientHandlerException("Adding entity to http method " + cr.getMethod() + " is not supported.");
+    }
+
+    return request;
+  }
+
+  private HttpEntity getHttpEntity(final ClientRequest cr) {
+    final Object entity = cr.getEntity();
+
+    if (entity == null)
+      return null;
+
+    final RequestEntityWriter requestEntityWriter = getRequestEntityWriter(cr);
+
+    try {
+      HttpEntity httpEntity = new AbstractHttpEntity() {
+        @Override
+        public boolean isRepeatable() {
+          return false;
+        }
+
+        @Override
+        public long getContentLength() {
+          return requestEntityWriter.getSize();
+        }
+
+        @Override
+        public InputStream getContent() throws IOException, IllegalStateException {
+          return null;
+        }
+
+        @Override
+        public void writeTo(OutputStream outputStream) throws IOException {
+          requestEntityWriter.writeRequestEntity(outputStream);
+        }
+
+        @Override
+        public boolean isStreaming() {
+          return false;
+        }
+      };
+
+      if (cr.getProperties().get(ClientConfig.PROPERTY_CHUNKED_ENCODING_SIZE) != null) {
+        // TODO return InputStreamEntity
+        return httpEntity;
+      } else {
+        return new BufferedHttpEntity(httpEntity);
+      }
+    } catch (Exception ex) {
+      // TODO warning/error?
+    }
+
+    return null;
+  }
+
+  private InBoundHeaders getInBoundHeaders(final HttpResponse response) {
+    final InBoundHeaders headers = new InBoundHeaders();
+    final Header[] respHeaders = response.getAllHeaders();
+    for (Header header : respHeaders) {
+      List<String> list = headers.get(header.getName());
+      if (list == null) {
+        list = new ArrayList<String>();
+      }
+      list.add(header.getValue());
+      headers.put(header.getName(), list);
+    }
+    return headers;
+  }
+
+  private static final class HttpClientResponseInputStream extends FilterInputStream {
+
+    HttpClientResponseInputStream(final HttpResponse response) throws IOException {
+      super(getInputStream(response));
+    }
+
+    @Override
+    public void close()
+      throws IOException {
+      super.close();
+    }
+  }
+
+  private static InputStream getInputStream(final HttpResponse response) throws IOException {
+
+    if (response.getEntity() == null) {
+      return new ByteArrayInputStream(new byte[0]);
+    } else {
+      final InputStream i = response.getEntity().getContent();
+      if (i.markSupported())
+        return i;
+      return new BufferedInputStream(i, ReaderWriter.BUFFER_SIZE);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/UnixSocketSessionInputBuffer.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/UnixSocketSessionInputBuffer.java b/docker-java/src/main/java/com/kpelykh/docker/client/UnixSocketSessionInputBuffer.java
new file mode 100644
index 0000000..9c7f150
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/UnixSocketSessionInputBuffer.java
@@ -0,0 +1,23 @@
+package com.kpelykh.docker.client;
+
+import org.apache.http.impl.io.AbstractSessionInputBuffer;
+import org.apache.http.params.HttpParams;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ *
+ */
+public class UnixSocketSessionInputBuffer extends AbstractSessionInputBuffer {
+
+  @Override
+  protected void init(InputStream instream, int buffersize, HttpParams params) {
+    super.init(instream, buffersize, params);
+  }
+
+  @Override
+  public boolean isDataAvailable(int timeout) throws IOException {
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/UnixSocketSessionOutputBuffer.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/UnixSocketSessionOutputBuffer.java b/docker-java/src/main/java/com/kpelykh/docker/client/UnixSocketSessionOutputBuffer.java
new file mode 100644
index 0000000..411096f
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/UnixSocketSessionOutputBuffer.java
@@ -0,0 +1,17 @@
+package com.kpelykh.docker.client;
+
+import org.apache.http.impl.io.AbstractSessionOutputBuffer;
+import org.apache.http.params.HttpParams;
+
+import java.io.OutputStream;
+
+/**
+ * {@link org.apache.http.impl.io.AbstractSessionOutputBuffer} implementation for UNIX sockets.
+ */
+public class UnixSocketSessionOutputBuffer extends AbstractSessionOutputBuffer {
+
+  @Override
+  protected void init(OutputStream outstream, int buffersize, HttpParams params) {
+    super.init(outstream, buffersize, params);
+  }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/BoundHostVolumes.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/BoundHostVolumes.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/BoundHostVolumes.java
new file mode 100644
index 0000000..c5c30de
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/BoundHostVolumes.java
@@ -0,0 +1,93 @@
+/**
+ * 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.kpelykh.docker.client.model;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.map.JsonSerializer;
+import org.codehaus.jackson.map.SerializerProvider;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+
+/**
+ * @author Kevin A. Archie <ka...@wustl.edu>
+ *
+ */
+@JsonSerialize(using=BoundHostVolumes.Serializer.class)
+public class BoundHostVolumes {
+    private static final String[] STRING_ARRAY = new String[0];
+    private final String[] dests, binds;
+
+    /**
+     * 
+     * @param specs Iterable of String binding specs, each of form "{host-path}:{container-patch}:[rw|ro]"
+     * @throws MalformedVolumeSpecException if any specs are null or empty
+     */
+    public BoundHostVolumes(final Iterable<String> specs) {
+        final List<String> dests = new ArrayList<String>(), binds = new ArrayList<String>();
+        for (final String spec : specs) {
+            if (null == spec || "".equals(spec)) {
+                // skip empty spec lines
+            } else {
+                final String[] sspec = spec.split(":");
+                dests.add(sspec.length > 1 ? sspec[1] : sspec[0]);
+                binds.add(spec);
+            }
+        }
+        this.dests = dests.toArray(STRING_ARRAY);
+        this.binds = binds.toArray(STRING_ARRAY);
+    }
+
+    public String[] asBinds() {
+        return binds;
+    }
+
+    private BoundHostVolumes writeVolumes(final JsonGenerator jg) throws IOException {
+        jg.writeStartObject();
+        for (final String dest : dests) {
+            jg.writeObjectFieldStart(dest);
+            jg.writeEndObject();
+        }
+        jg.writeEndObject();
+        return this;
+    }
+
+    /**
+     * This is an ugly hack. We assume that the serializer only gets called when
+     * a containing ContainerConfig gets serialized, when POSTing to
+     * /containers/create . In that context, we pass only the container-path
+     * part (the key in the volumes map).
+     * 
+     * @author Kevin A. Archie <ka...@wustl.edu>
+     * 
+     */
+    public static class Serializer extends JsonSerializer<BoundHostVolumes> {
+        /* (non-Javadoc)
+         * @see org.codehaus.jackson.map.JsonSerializer#serialize(java.lang.Object, org.codehaus.jackson.JsonGenerator, org.codehaus.jackson.map.SerializerProvider)
+         */
+        @Override
+        public void serialize(final BoundHostVolumes volumes, final JsonGenerator jg, final SerializerProvider sp)
+                throws IOException {
+            volumes.writeVolumes(jg);
+        }       
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/ChangeLog.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/ChangeLog.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/ChangeLog.java
new file mode 100644
index 0000000..be6df3a
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/ChangeLog.java
@@ -0,0 +1,33 @@
+package com.kpelykh.docker.client.model;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ *
+ * @author Konstantin Pelykh (kpelykh@gmail.com)
+ *
+ */
+public class ChangeLog {
+
+    @JsonProperty("Path")
+    private String path;
+
+    @JsonProperty("Kind")
+    private int kind;
+
+    public String getPath() {
+        return path;
+    }
+
+    public int getKind() {
+        return kind;
+    }
+
+    @Override
+    public String toString() {
+        return "ChangeLog{" +
+                "path='" + path + '\'' +
+                ", kind=" + kind +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java
new file mode 100644
index 0000000..69af995
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/CommitConfig.java
@@ -0,0 +1,85 @@
+package com.kpelykh.docker.client.model;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ *
+ * @author Konstantin Pelykh (kpelykh@gmail.com)
+ *
+ */
+public class CommitConfig {
+
+    @JsonProperty("container")
+    private String container;
+
+    @JsonProperty("repo")
+    private String repo;
+
+    @JsonProperty("tag")
+    private String tag;
+
+    @JsonProperty("m")
+    private String message;
+
+    //author (eg. “John Hannibal Smith <ha...@a-team.com>”)
+    @JsonProperty("author")
+    private String author;
+
+    //config automatically applied when the image is run. (ex: {“Cmd”: [“cat”, “/world”], “PortSpecs”:[“22”]})
+    @JsonProperty("run")
+    private String run;
+
+    public String getContainer() {
+        return container;
+    }
+
+    public String getRepo() {
+        return repo;
+    }
+
+    public String getTag() {
+        return tag;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public String getAuthor() {
+        return author;
+    }
+
+    public String getRun() {
+        return run;
+    }
+
+    public CommitConfig setRepo(String repo) {
+        this.repo = repo;
+        return this;
+    }
+
+    public CommitConfig setTag(String tag) {
+        this.tag = tag;
+        return this;
+    }
+
+    public CommitConfig setMessage(String message) {
+        this.message = message;
+        return this;
+    }
+
+    public CommitConfig setAuthor(String author) {
+        this.author = author;
+        return this;
+    }
+
+    public CommitConfig setRun(String run) {
+        this.run = run;
+        return this;
+    }
+
+    public CommitConfig(String container) {
+        this.container = container;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/Container.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/Container.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/Container.java
new file mode 100644
index 0000000..14970c3
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/Container.java
@@ -0,0 +1,140 @@
+package com.kpelykh.docker.client.model;
+
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import java.util.Arrays;
+
+/**
+ *
+ * @author Konstantin Pelykh (kpelykh@gmail.com)
+ *
+ */
+@JsonIgnoreProperties(ignoreUnknown=true)
+public class Container {
+
+    @JsonProperty("Id")
+    private String id;
+
+    @JsonProperty("Command")
+    private String command;
+
+    @JsonProperty("Image")
+    private String image;
+
+    @JsonProperty("Created")
+    private long created;
+
+    @JsonProperty("Status")
+    private String status;
+
+    /* Example:
+    "Ports": {
+        "22/tcp": [
+            {
+                "HostIp": "0.0.0.0",
+                "HostPort": "8022"
+            }
+        ]
+    }
+    */
+
+    @JsonProperty("Ports")    
+    public Ports ports;
+
+    @JsonProperty("SizeRw")
+    private int size;
+
+    @JsonProperty("SizeRootFs")
+    private int sizeRootFs;
+
+    @JsonProperty("Names")
+    private String[] names;
+
+    public String getId() {
+        return id;
+    }
+
+    public String getCommand() {
+        return command;
+    }
+
+    public String getImage() {
+        return image;
+    }
+
+    public long getCreated() {
+        return created;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public Ports getPorts() {
+        return ports;
+    }
+
+    public void setPorts(Ports ports) {
+        this.ports = ports;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    public int getSizeRootFs() {
+        return sizeRootFs;
+    }
+
+    public String[] getNames() {
+        return names;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public void setCommand(String command) {
+        this.command = command;
+    }
+
+    public void setImage(String image) {
+        this.image = image;
+    }
+
+    public void setCreated(long created) {
+        this.created = created;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public void setSize(int size) {
+        this.size = size;
+    }
+
+    public void setSizeRootFs(int sizeRootFs) {
+        this.sizeRootFs = sizeRootFs;
+    }
+
+    public void setNames(String[] names) {
+        this.names = names;
+    }
+
+    @Override
+    public String toString() {
+        return "Container{" +
+                "id='" + id + '\'' +
+                ", command='" + command + '\'' +
+                ", image='" + image + '\'' +
+                ", created=" + created +
+                ", status='" + status + '\'' +
+                ", ports=" + ports +
+                ", size=" + size +
+                ", sizeRootFs=" + sizeRootFs +
+                ", names=" + Arrays.toString(names) +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java
new file mode 100644
index 0000000..a756a4e
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/ContainerConfig.java
@@ -0,0 +1,282 @@
+package com.kpelykh.docker.client.model;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ *
+ * @author Konstantin Pelykh (kpelykh@gmail.com)
+ *
+ */
+public class ContainerConfig {
+
+    @JsonProperty("Hostname")     private String    hostName = "";
+    @JsonProperty("PortSpecs")    private String[]  portSpecs;
+    @JsonProperty("User")         private String    user = "";
+    @JsonProperty("Tty")          private boolean   tty = false;
+    @JsonProperty("OpenStdin")    private boolean   stdinOpen = false;
+    @JsonProperty("StdinOnce")    private boolean   stdInOnce = false;
+    @JsonProperty("Memory")       private long      memoryLimit = 0;
+    @JsonProperty("MemorySwap")   private long      memorySwap = 0;
+    @JsonProperty("CpuShares")    private int       cpuShares = 0;
+    @JsonProperty("AttachStdin")  private boolean   attachStdin = false;
+    @JsonProperty("AttachStdout") private boolean   attachStdout = false;
+    @JsonProperty("AttachStderr") private boolean   attachStderr = false;
+    @JsonProperty("Env")          private String[]  env;
+    @JsonProperty("Cmd")          private String[]  cmd;
+    @JsonProperty("Dns")          private String[]  dns;
+    @JsonProperty("Image")        private String    image;
+    @JsonProperty("Volumes")      private BoundHostVolumes   volumes;
+    @JsonProperty("VolumesFrom")  private String    volumesFrom = "";
+    @JsonProperty("Entrypoint")   private String[]  entrypoint = new String[]{};
+    @JsonProperty("NetworkDisabled") private boolean networkDisabled = false;
+    @JsonProperty("Privileged")   private boolean privileged = false;
+    @JsonProperty("WorkingDir")   private String workingDir = "";
+    @JsonProperty("Domainname")   private String domainName = "";
+    // FIXME Is this the right type? -BJE
+    @JsonProperty("ExposedPorts")   private Map<String, ?> exposedPorts;
+    @JsonProperty("OnBuild")          private String[]  onBuild;
+
+    public Map<String, ?> getExposedPorts() {
+        return exposedPorts;
+    }
+
+    public boolean isNetworkDisabled() {
+        return networkDisabled;
+    }
+
+    public String getDomainName() {
+        return domainName;
+    }
+
+    public String getWorkingDir() { return workingDir; }
+
+    public ContainerConfig setWorkingDir(String workingDir) {
+        this.workingDir = workingDir;
+        return this;
+    }
+
+    public boolean isPrivileged() {
+        return privileged;
+    }
+
+    public ContainerConfig setPrivileged(boolean privileged) {
+        this.privileged = privileged;
+        return this;
+    }
+
+    public String getHostName() {
+        return hostName;
+    }
+
+    public ContainerConfig setNetworkDisabled(boolean networkDisabled) {
+        this.networkDisabled = networkDisabled;
+        return this;
+    }
+
+    public ContainerConfig setHostName(String hostName) {
+        this.hostName = hostName;
+        return this;
+    }
+
+    public String[] getPortSpecs() {
+        return portSpecs;
+    }
+
+    public ContainerConfig setPortSpecs(String[] portSpecs) {
+        this.portSpecs = portSpecs;
+        return this;
+    }
+
+    public String getUser() {
+        return user;
+    }
+
+    public ContainerConfig setUser(String user) {
+        this.user = user;
+        return this;
+    }
+
+    public boolean isTty() {
+        return tty;
+    }
+
+    public ContainerConfig setTty(boolean tty) {
+        this.tty = tty;
+        return this;
+    }
+
+    public boolean isStdinOpen() {
+        return stdinOpen;
+    }
+
+    public ContainerConfig setStdinOpen(boolean stdinOpen) {
+        this.stdinOpen = stdinOpen;
+        return this;
+    }
+
+    public boolean isStdInOnce() {
+        return stdInOnce;
+    }
+
+    public ContainerConfig setStdInOnce(boolean stdInOnce) {
+        this.stdInOnce = stdInOnce;
+        return this;
+    }
+
+    public long getMemoryLimit() {
+        return memoryLimit;
+    }
+
+    public ContainerConfig setMemoryLimit(long memoryLimit) {
+        this.memoryLimit = memoryLimit;
+        return this;
+    }
+
+    public long getMemorySwap() {
+        return memorySwap;
+    }
+
+    public ContainerConfig setMemorySwap(long memorySwap) {
+        this.memorySwap = memorySwap;
+        return this;
+    }
+
+    public int getCpuShares() {
+        return cpuShares;
+    }
+
+    public ContainerConfig setCpuShares(int cpuShares) {
+        this.cpuShares = cpuShares;
+        return this;
+    }
+
+    public boolean isAttachStdin() {
+        return attachStdin;
+    }
+
+    public ContainerConfig setAttachStdin(boolean attachStdin) {
+        this.attachStdin = attachStdin;
+        return this;
+    }
+
+    public boolean isAttachStdout() {
+        return attachStdout;
+    }
+
+    public ContainerConfig setAttachStdout(boolean attachStdout) {
+        this.attachStdout = attachStdout;
+        return this;
+    }
+
+    public boolean isAttachStderr() {
+        return attachStderr;
+    }
+
+    public ContainerConfig setAttachStderr(boolean attachStderr) {
+        this.attachStderr = attachStderr;
+        return this;
+    }
+
+    public String[] getEnv() {
+        return env;
+    }
+
+    public ContainerConfig setEnv(String[] env) {
+        this.env = env;
+        return this;
+    }
+
+    public String[] getCmd() {
+        return cmd;
+    }
+
+    public ContainerConfig setCmd(String[] cmd) {
+        this.cmd = cmd;
+        return this;
+    }
+
+    public String[] getDns() {
+        return dns;
+    }
+
+    public ContainerConfig setDns(String[] dns) {
+        this.dns = dns;
+        return this;
+    }
+
+    public String getImage() {
+        return image;
+    }
+
+    public ContainerConfig setImage(String image) {
+        this.image = image;
+        return this;
+    }
+
+    public BoundHostVolumes getVolumes() {
+        return volumes;
+    }
+
+    public ContainerConfig setVolumes(BoundHostVolumes volumes) {
+        this.volumes = volumes;
+        return this;
+    }
+
+    public String getVolumesFrom() {
+        return volumesFrom;
+    }
+
+    public ContainerConfig setVolumesFrom(String volumesFrom) {
+        this.volumesFrom = volumesFrom;
+        return this;
+    }
+
+    public String[] getEntrypoint() {
+        return entrypoint;
+    }
+
+    public ContainerConfig setEntrypoint(String[] entrypoint) {
+        this.entrypoint = entrypoint;
+        return this;
+    }
+
+    public String[] getOnBuild() {
+	return onBuild;
+    }
+
+    public void setOnBuild(String[] onBuild) {
+	this.onBuild=onBuild;
+    }
+
+    @Override
+    public String toString() {
+        return "ContainerConfig{" +
+                "hostName='" + hostName + '\'' +
+                ", portSpecs=" + Arrays.toString(portSpecs) +
+                ", user='" + user + '\'' +
+                ", tty=" + tty +
+                ", stdinOpen=" + stdinOpen +
+                ", stdInOnce=" + stdInOnce +
+                ", memoryLimit=" + memoryLimit +
+                ", memorySwap=" + memorySwap +
+                ", cpuShares=" + cpuShares +
+                ", attachStdin=" + attachStdin +
+                ", attachStdout=" + attachStdout +
+                ", attachStderr=" + attachStderr +
+                ", env=" + Arrays.toString(env) +
+                ", cmd=" + Arrays.toString(cmd) +
+                ", dns=" + Arrays.toString(dns) +
+                ", image='" + image + '\'' +
+                ", volumes=" + volumes +
+                ", volumesFrom='" + volumesFrom + '\'' +
+                ", entrypoint=" + Arrays.toString(entrypoint) +
+                ", networkDisabled=" + networkDisabled +
+                ", privileged=" + privileged +
+                ", workingDir='" + workingDir + '\'' +
+                ", domainName='" + domainName + '\'' +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/ContainerCreateResponse.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/ContainerCreateResponse.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/ContainerCreateResponse.java
new file mode 100644
index 0000000..d56d677
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/ContainerCreateResponse.java
@@ -0,0 +1,43 @@
+package com.kpelykh.docker.client.model;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import java.util.Arrays;
+
+/**
+ *
+ * @author Konstantin Pelykh (kpelykh@gmail.com)
+ *
+ */
+public class ContainerCreateResponse {
+
+    @JsonProperty("Id")
+    private String id;
+
+    @JsonProperty("Warnings")
+    private String[] warnings;
+
+    public String getId() {
+        return id;
+    }
+
+    public String[] getWarnings() {
+        return warnings;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public void setWarnings(String[] warnings) {
+        this.warnings = warnings;
+    }
+
+    @Override
+    public String toString() {
+        return "ContainerCreateResponse{" +
+                "id='" + id + '\'' +
+                ", warnings=" + Arrays.toString(warnings) +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java
new file mode 100644
index 0000000..04d2f8c
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/ContainerInspectResponse.java
@@ -0,0 +1,247 @@
+package com.kpelykh.docker.client.model;
+
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import java.util.Arrays;
+import java.util.Map;
+
+/**
+ *
+ * @author Konstantin Pelykh (kpelykh@gmail.com)
+ *
+ */
+public class ContainerInspectResponse {
+
+    @JsonProperty("ID")
+    private String id;
+
+    @JsonProperty("Created")
+    private String created;
+
+    @JsonProperty("Path")
+    private String path;
+
+    @JsonProperty("Args")
+    private String[] args;
+
+    @JsonProperty("Config")
+    public ContainerConfig config;
+
+    @JsonProperty("State")
+    private ContainerState state;
+
+    @JsonProperty("Image")
+    private String image;
+
+    @JsonProperty("NetworkSettings")
+    private NetworkSettings networkSettings;
+
+    @JsonProperty("SysInitPath")
+    private String sysInitPath;
+
+    @JsonProperty("ResolvConfPath")
+    private String resolvConfPath;
+
+    @JsonProperty("Volumes")
+    private Map<String, String> volumes;
+
+    @JsonProperty("VolumesRW")
+    private Map<String, String> volumesRW;
+
+    @JsonProperty("HostnamePath")
+    private String hostnamePath;
+
+    @JsonProperty("HostsPath")
+    private String hostsPath;
+
+    @JsonProperty("Name")
+    private String name;
+
+    @JsonProperty("Driver")
+    private String driver;
+
+    @JsonProperty("HostConfig")
+    private HostConfig hostConfig;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getCreated() {
+        return created;
+    }
+
+    public void setCreated(String created) {
+        this.created = created;
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    public void setPath(String path) {
+        this.path = path;
+    }
+
+    public String[] getArgs() {
+        return args;
+    }
+
+    public void setArgs(String[] args) {
+        this.args = args;
+    }
+
+    public ContainerConfig getConfig() {
+        return config;
+    }
+
+    public void setConfig(ContainerConfig config) {
+        this.config = config;
+    }
+
+    public ContainerState getState() {
+        return state;
+    }
+
+    public void setState(ContainerState state) {
+        this.state = state;
+    }
+
+    public String getImage() {
+        return image;
+    }
+
+    public void setImage(String image) {
+        this.image = image;
+    }
+
+    public NetworkSettings getNetworkSettings() {
+        return networkSettings;
+    }
+
+    public void setNetworkSettings(NetworkSettings networkSettings) {
+        this.networkSettings = networkSettings;
+    }
+
+    public String getSysInitPath() {
+        return sysInitPath;
+    }
+
+    public void setSysInitPath(String sysInitPath) {
+        this.sysInitPath = sysInitPath;
+    }
+
+    public String getResolvConfPath() {
+        return resolvConfPath;
+    }
+
+    public void setResolvConfPath(String resolvConfPath) {
+        this.resolvConfPath = resolvConfPath;
+    }
+
+    public Map<String, String> getVolumes() {
+        return volumes;
+    }
+
+    public void setVolumes(Map<String, String> volumes) {
+        this.volumes = volumes;
+    }
+
+    public Map<String, String> getVolumesRW() {
+        return volumesRW;
+    }
+
+    public void setVolumesRW(Map<String, String> volumesRW) {
+        this.volumesRW = volumesRW;
+    }
+
+    public String getHostnamePath() {
+        return hostnamePath;
+    }
+
+    public void setHostnamePath(String hostnamePath) {
+        this.hostnamePath = hostnamePath;
+    }
+
+    public String getHostsPath() {
+        return hostsPath;
+    }
+
+    public void setHostsPath(String hostsPath) {
+        this.hostsPath = hostsPath;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDriver() {
+        return driver;
+    }
+
+    public void setDriver(String driver) {
+        this.driver = driver;
+    }
+
+    public HostConfig getHostConfig() {
+        return hostConfig;
+    }
+
+    public void setHostConfig(HostConfig hostConfig) {
+        this.hostConfig = hostConfig;
+    }
+
+    public class NetworkSettings {
+
+        @JsonProperty("IPAddress") public String ipAddress;
+        @JsonProperty("IPPrefixLen") public int ipPrefixLen;
+        @JsonProperty("Gateway") public String gateway;
+        @JsonProperty("Bridge") public String bridge;
+        @JsonProperty("PortMapping") public Map<String,Map<String, String>> portMapping;
+        @JsonProperty("Ports") public Ports ports;
+
+        @Override
+        public String toString() {
+            return "NetworkSettings{" +
+                    "ports=" + ports +
+                    ", portMapping=" + portMapping +
+                    ", bridge='" + bridge + '\'' +
+                    ", gateway='" + gateway + '\'' +
+                    ", ipPrefixLen=" + ipPrefixLen +
+                    ", ipAddress='" + ipAddress + '\'' +
+                    '}';
+        }
+    }
+
+    public class ContainerState {
+
+        @JsonProperty("Running") public boolean running;
+        @JsonProperty("Pid") public int pid;
+        @JsonProperty("ExitCode") public int exitCode;
+        @JsonProperty("StartedAt") public String startedAt;
+        @JsonProperty("Ghost") public boolean ghost;
+        @JsonProperty("FinishedAt") private String finishedAt;
+
+        @Override
+        public String toString() {
+            return "ContainerState{" +
+                    "running=" + running +
+                    ", pid=" + pid +
+                    ", exitCode=" + exitCode +
+                    ", startedAt='" + startedAt + '\'' +
+                    ", ghost=" + ghost +
+                    ", finishedAt='" + finishedAt + '\'' +
+                    '}';
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/CopyConfig.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/CopyConfig.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/CopyConfig.java
new file mode 100755
index 0000000..f94106c
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/CopyConfig.java
@@ -0,0 +1,61 @@
+package com.kpelykh.docker.client.model;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ * Configuration object for copy command.
+ * @author Victor Lyuboslavsky
+ */
+public class CopyConfig {
+
+    @JsonProperty("HostPath")
+    private String hostPath;
+
+    @JsonProperty("Resource")
+    private String resource;
+
+    /**
+     * Constructor.
+     */
+    public CopyConfig() {
+        hostPath = ".";
+    }
+
+    /**
+     * Retrieves the 'resource' variable.
+     * @return the 'resource' variable value
+     */
+    public String getResource() {
+        return resource;
+    }
+
+    /**
+     * Sets the 'resource' variable.
+     * @param resource the new 'resource' variable value to set
+     */
+    public void setResource(String resource) {
+        this.resource = resource;
+    }
+
+    /**
+     * Retrieves the 'hostPath' variable.
+     * @return the 'hostPath' variable value
+     */
+    public String getHostPath() {
+        return hostPath;
+    }
+
+    /**
+     * Sets the 'hostPath' variable.
+     * @param hostPath the new 'hostPath' variable value to set
+     */
+    public void setHostPath(String hostPath) {
+        this.hostPath = hostPath;
+    }
+
+    @Override
+    public String toString() {
+        return "{\"HostPath\":\"" + hostPath + "\", \"Resource\":\"" + resource + "\"}";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/DriverStatus.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/DriverStatus.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/DriverStatus.java
new file mode 100644
index 0000000..2ed1922
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/DriverStatus.java
@@ -0,0 +1,31 @@
+package com.kpelykh.docker.client.model;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ * Created by ben on 12/12/13.
+ */
+public class DriverStatus {
+
+    @JsonProperty("Root Dir")
+    private String rootDir;
+
+    @JsonProperty("Dirs")
+    private int dirs;
+
+    public String getRootDir() {
+        return rootDir;
+    }
+
+    public int getDirs() {
+        return dirs;
+    }
+
+    @Override
+    public String toString() {
+        return "DriverStatus{" +
+                "rootDir='" + rootDir + '\'' +
+                ", dirs=" + dirs +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/HostConfig.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/HostConfig.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/HostConfig.java
new file mode 100644
index 0000000..47a12fe
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/HostConfig.java
@@ -0,0 +1,148 @@
+package com.kpelykh.docker.client.model;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import java.util.Arrays;
+
+/**
+ *
+ * @author Konstantin Pelykh (kpelykh@gmail.com)
+ *
+ */
+public class HostConfig {
+
+    @JsonProperty("Binds")
+    private String[] binds;
+
+    @JsonProperty("ContainerIDFile")
+    private String containerIDFile;
+
+    @JsonProperty("LxcConf")
+    private LxcConf[] lxcConf;
+
+
+    @JsonProperty("Links")
+    private String[] links;
+
+    @JsonProperty("PortBindings")
+    private Ports portBindings;
+
+    @JsonProperty("Privileged")
+    private boolean privileged;
+
+    @JsonProperty("PublishAllPorts")
+    private boolean publishAllPorts;
+
+    public HostConfig() {
+        this.binds = null;
+    }
+
+
+    public String[] getBinds() {
+        return binds;
+    }
+
+    public void setBinds(String[] binds) {
+        this.binds = binds;
+    }
+    
+    public void setBinds(final BoundHostVolumes volumes) {
+        setBinds(volumes.asBinds());
+    }
+
+    public String getContainerIDFile() {
+        return containerIDFile;
+    }
+
+    public void setContainerIDFile(String containerIDFile) {
+        this.containerIDFile = containerIDFile;
+    }
+
+    public LxcConf[] getLxcConf() {
+        return lxcConf;
+    }
+
+    public void setLxcConf(LxcConf[] lxcConf) {
+        this.lxcConf = lxcConf;
+    }
+
+    public String[] getLinks() {
+        return links;
+    }
+
+    public void setLinks(String[] links) {
+        this.links = links;
+    }
+
+    public Ports getPortBindings() {
+        return portBindings;
+    }
+
+    public void setPortBindings(Ports portBindings) {
+        this.portBindings = portBindings;
+    }
+
+    public boolean isPrivileged() {
+        return privileged;
+    }
+
+    public void setPrivileged(boolean privileged) {
+        this.privileged = privileged;
+    }
+
+    public boolean isPublishAllPorts() {
+        return publishAllPorts;
+    }
+
+    public void setPublishAllPorts(boolean publishAllPorts) {
+        this.publishAllPorts = publishAllPorts;
+    }
+
+    @Override
+    public String toString() {
+        return "HostConfig{" +
+                "binds=" + Arrays.toString(binds) +
+                ", containerIDFile='" + containerIDFile + '\'' +
+                ", lxcConf=" + Arrays.toString(lxcConf) +
+                ", links=" + Arrays.toString(links) +
+                ", portBindings=" + portBindings +
+                ", privileged=" + privileged +
+                ", publishAllPorts=" + publishAllPorts +
+                '}';
+    }
+
+    public class LxcConf {
+        @JsonProperty("Key")
+        public String key;
+
+        @JsonProperty("Value")
+        public String value;
+
+        public LxcConf(String key, String value) {
+            this.key = key;
+            this.value = value;
+        }
+
+        public LxcConf() {
+        }
+
+        public String getKey() {
+            return key;
+        }
+
+        public LxcConf setKey(String key) {
+            this.key = key;
+            return this;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        public LxcConf setValue(String value) {
+            this.value = value;
+            return this;
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/IBuilder.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/IBuilder.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/IBuilder.java
new file mode 100644
index 0000000..7f5f160
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/IBuilder.java
@@ -0,0 +1,9 @@
+package com.kpelykh.docker.client.model;
+
+/**
+ * Created by ben on 12/12/13.
+ */
+public interface IBuilder<T> {
+
+    T build();
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/Image.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/Image.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/Image.java
new file mode 100644
index 0000000..4b68590
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/Image.java
@@ -0,0 +1,116 @@
+package com.kpelykh.docker.client.model;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import java.util.Arrays;
+
+/**
+ *
+ * @author Konstantin Pelykh (kpelykh@gmail.com)
+ *
+ */
+public class Image {
+
+    @JsonProperty("Id")
+    private String id;
+
+    @JsonProperty("RepoTags")
+    private String[] repoTags;
+
+    @JsonProperty("Repository")
+    private String repository;
+
+    @JsonProperty("Tag")
+    private String tag;
+
+
+    @JsonProperty("ParentId")
+    private String parentId;
+
+    @JsonProperty("Created")
+    private long created;
+
+    @JsonProperty("Size")
+    private long size;
+
+    @JsonProperty("VirtualSize")
+    private long virtualSize;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String[] getRepoTags() {
+        return repoTags;
+    }
+
+    public void setRepoTags(String[] repoTags) {
+        this.repoTags = repoTags;
+    }
+
+    public String getRepository() {
+        return repository;
+    }
+
+    public void setRepository(String repository) {
+        this.repository = repository;
+    }
+
+    public String getTag() {
+        return tag;
+    }
+
+    public void setTag(String tag) {
+        this.tag = tag;
+    }
+
+    public String getParentId() {
+        return parentId;
+    }
+
+    public void setParentId(String parentId) {
+        this.parentId = parentId;
+    }
+
+    public long getCreated() {
+        return created;
+    }
+
+    public void setCreated(long created) {
+        this.created = created;
+    }
+
+    public long getSize() {
+        return size;
+    }
+
+    public void setSize(long size) {
+        this.size = size;
+    }
+
+    public long getVirtualSize() {
+        return virtualSize;
+    }
+
+    public void setVirtualSize(long virtualSize) {
+        this.virtualSize = virtualSize;
+    }
+
+    @Override
+    public String toString() {
+        return "Image{" +
+                "virtualSize=" + virtualSize +
+                ", id='" + id + '\'' +
+                ", repoTags=" + Arrays.toString(repoTags) +
+                ", repository='" + repository + '\'' +
+                ", tag='" + tag + '\'' +
+                ", parentId='" + parentId + '\'' +
+                ", created=" + created +
+                ", size=" + size +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/ImageCreateResponse.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/ImageCreateResponse.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/ImageCreateResponse.java
new file mode 100644
index 0000000..4be6807
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/ImageCreateResponse.java
@@ -0,0 +1,30 @@
+package com.kpelykh.docker.client.model;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import java.util.Arrays;
+
+/**
+ * Parse reponses from /images/create
+ *
+ * @author Ryan Campbell (ryan.campbell@gmail.com)
+ *
+ */
+public class ImageCreateResponse {
+
+    @JsonProperty("status")
+    private String id;
+
+
+    public String getId() {
+        return id;
+    }
+
+
+    @Override
+    public String toString() {
+        return "ContainerCreateResponse{" +
+                "id='" + id + '\'' +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java
new file mode 100644
index 0000000..4b714f4
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/ImageInspectResponse.java
@@ -0,0 +1,150 @@
+package com.kpelykh.docker.client.model;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ *
+ * @author Konstantin Pelykh (kpelykh@gmail.com)
+ *
+ */
+public class ImageInspectResponse {
+
+    @JsonProperty("id")
+    private String id;
+
+    @JsonProperty("parent") private String parent;
+
+    @JsonProperty("created") private String created;
+
+    @JsonProperty("container") private String container;
+
+    @JsonProperty("container_config") private ContainerConfig containerConfig;
+
+    @JsonProperty("Size") private int size;
+
+    @JsonProperty("docker_version") private String dockerVersion;
+
+    @JsonProperty("config") private ContainerConfig config;
+
+    @JsonProperty("architecture") private String arch;
+
+    @JsonProperty("comment") private String comment;
+
+    @JsonProperty("author") private String author;
+
+    @JsonProperty("os") private String os;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getParent() {
+        return parent;
+    }
+
+    public void setParent(String parent) {
+        this.parent = parent;
+    }
+
+    public String getCreated() {
+        return created;
+    }
+
+    public void setCreated(String created) {
+        this.created = created;
+    }
+
+    public String getContainer() {
+        return container;
+    }
+
+    public void setContainer(String container) {
+        this.container = container;
+    }
+
+    public ContainerConfig getContainerConfig() {
+        return containerConfig;
+    }
+
+    public void setContainerConfig(ContainerConfig containerConfig) {
+        this.containerConfig = containerConfig;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    public void setSize(int size) {
+        this.size = size;
+    }
+
+    public String getDockerVersion() {
+        return dockerVersion;
+    }
+
+    public void setDockerVersion(String dockerVersion) {
+        this.dockerVersion = dockerVersion;
+    }
+
+    public ContainerConfig getConfig() {
+        return config;
+    }
+
+    public void setConfig(ContainerConfig config) {
+        this.config = config;
+    }
+
+    public String getArch() {
+        return arch;
+    }
+
+    public void setArch(String arch) {
+        this.arch = arch;
+    }
+
+    public String getComment() {
+        return comment;
+    }
+
+    public void setComment(String comment) {
+        this.comment = comment;
+    }
+
+    public String getAuthor() {
+        return author;
+    }
+
+    public void setAuthor(String author) {
+        this.author = author;
+    }
+
+    public String getOs() {
+        return os;
+    }
+
+    public void setOs(String os) {
+        this.os = os;
+    }
+
+    @Override
+    public String toString() {
+        return "ImageInspectResponse{" +
+                "id='" + id + '\'' +
+                ", parent='" + parent + '\'' +
+                ", created='" + created + '\'' +
+                ", container='" + container + '\'' +
+                ", containerConfig=" + containerConfig +
+                ", size=" + size +
+                ", dockerVersion='" + dockerVersion + '\'' +
+                ", config=" + config +
+                ", arch='" + arch + '\'' +
+                ", comment='" + comment + '\'' +
+                ", author='" + author + '\'' +
+                ", os='" + os + '\'' +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/Info.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/Info.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/Info.java
new file mode 100644
index 0000000..f340dc8
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/Info.java
@@ -0,0 +1,225 @@
+package com.kpelykh.docker.client.model;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+import java.util.List;
+
+/**
+ *
+ * @author Konstantin Pelykh (kpelykh@gmail.com)
+ *
+ */
+@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
+public class Info {
+
+    @JsonProperty("Debug")
+    private boolean debug;
+
+    @JsonProperty("Containers")
+    private int    containers;
+
+    @JsonProperty("Driver")
+    private String driver;
+
+    @JsonProperty("DriverStatus")
+    private List<Object> driverStatuses;
+
+
+    @JsonProperty("Images")
+    private int    images;
+
+    @JsonProperty("IPv4Forwarding")
+    private String IPv4Forwarding;
+
+    @JsonProperty("IndexServerAddress")
+    private String IndexServerAddress;
+
+
+    @JsonProperty("InitPath")
+    private String initPath;
+
+    @JsonProperty("InitSha1")
+    private String initSha1;
+
+    @JsonProperty("KernelVersion")
+    private String kernelVersion;
+
+    @JsonProperty("LXCVersion")
+    private String lxcVersion;
+
+    @JsonProperty("MemoryLimit")
+    private boolean memoryLimit;
+
+    @JsonProperty("NEventsListener")
+    private long nEventListener;
+
+    @JsonProperty("NFd")
+    private int    NFd;
+
+    @JsonProperty("NGoroutines")
+    private int    NGoroutines;
+    
+    @JsonProperty("SwapLimit")
+    private int swapLimit;
+
+    @JsonProperty("ExecutionDriver")
+    private String executionDriver;
+
+    public boolean isDebug() {
+        return debug;
+    }
+
+    public void setDebug(boolean debug) {
+        this.debug = debug;
+    }
+
+    public int getContainers() {
+        return containers;
+    }
+
+    public void setContainers(int containers) {
+        this.containers = containers;
+    }
+
+    public String getDriver() {
+        return driver;
+    }
+
+    public void setDriver(String driver) {
+        this.driver = driver;
+    }
+
+    public List<Object> getDriverStatuses() {
+        return driverStatuses;
+    }
+
+    public void setDriverStatuses(List<Object> driverStatuses) {
+        this.driverStatuses = driverStatuses;
+    }
+
+    public int getImages() {
+        return images;
+    }
+
+    public void setImages(int images) {
+        this.images = images;
+    }
+
+    public String getIPv4Forwarding() {
+        return IPv4Forwarding;
+    }
+
+    public void setIPv4Forwarding(String IPv4Forwarding) {
+        this.IPv4Forwarding = IPv4Forwarding;
+    }
+
+    public String getIndexServerAddress() {
+        return IndexServerAddress;
+    }
+
+    public void setIndexServerAddress(String indexServerAddress) {
+        IndexServerAddress = indexServerAddress;
+    }
+
+    public String getInitPath() {
+        return initPath;
+    }
+
+    public void setInitPath(String initPath) {
+        this.initPath = initPath;
+    }
+
+    public String getInitSha1() {
+        return initSha1;
+    }
+
+    public void setInitSha1(String initSha1) {
+        this.initSha1 = initSha1;
+    }
+
+    public String getKernelVersion() {
+        return kernelVersion;
+    }
+
+    public void setKernelVersion(String kernelVersion) {
+        this.kernelVersion = kernelVersion;
+    }
+
+    public String getLxcVersion() {
+        return lxcVersion;
+    }
+
+    public void setLxcVersion(String lxcVersion) {
+        this.lxcVersion = lxcVersion;
+    }
+
+    public boolean isMemoryLimit() {
+        return memoryLimit;
+    }
+
+    public void setMemoryLimit(boolean memoryLimit) {
+        this.memoryLimit = memoryLimit;
+    }
+
+    public long getnEventListener() {
+        return nEventListener;
+    }
+
+    public void setnEventListener(long nEventListener) {
+        this.nEventListener = nEventListener;
+    }
+
+    public int getNFd() {
+        return NFd;
+    }
+
+    public void setNFd(int NFd) {
+        this.NFd = NFd;
+    }
+
+    public int getNGoroutines() {
+        return NGoroutines;
+    }
+
+    public void setNGoroutines(int NGoroutines) {
+        this.NGoroutines = NGoroutines;
+    }
+
+    public int getSwapLimit() {
+        return swapLimit;
+    }
+
+    public void setSwapLimit(int swapLimit) {
+        this.swapLimit = swapLimit;
+    }
+    public String getExecutionDriver() {
+        return executionDriver;
+    }
+
+    public void setExecutionDriver(String executionDriver) {
+        this.executionDriver=executionDriver;
+    }
+
+    @Override
+    public String toString() {
+        return "Info{" +
+                "debug=" + debug +
+                ", containers=" + containers +
+                ", driver='" + driver + '\'' +
+                ", driverStatuses=" + driverStatuses +
+                ", images=" + images +
+                ", IPv4Forwarding='" + IPv4Forwarding + '\'' +
+                ", IndexServerAddress='" + IndexServerAddress + '\'' +
+                ", initPath='" + initPath + '\'' +
+                ", initSha1='" + initSha1 + '\'' +
+                ", kernelVersion='" + kernelVersion + '\'' +
+                ", lxcVersion='" + lxcVersion + '\'' +
+                ", memoryLimit=" + memoryLimit +
+                ", nEventListener=" + nEventListener +
+                ", NFd=" + NFd +
+                ", NGoroutines=" + NGoroutines +
+                ", swapLimit=" + swapLimit +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/Port.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/Port.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/Port.java
new file mode 100644
index 0000000..b4fa913
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/Port.java
@@ -0,0 +1,52 @@
+package com.kpelykh.docker.client.model;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+  * @author <a href="mailto:nicolas.deloof@gmail.com">Nicolas De Loof</a>
+  */
+
+public class Port {
+
+    @JsonProperty("PrivatePort")
+    private long privatePort;
+
+    @JsonProperty("PublicPort")
+    private long publicPort;
+
+    @JsonProperty("Type")
+    private String type;
+
+    public long getPrivatePort() {
+        return privatePort;
+    }
+
+    public void setPrivatePort(long privatePort) {
+        this.privatePort = privatePort;
+    }
+
+    public long getPublicPort() {
+        return publicPort;
+    }
+
+    public void setPublicPort(long publicPort) {
+        this.publicPort = publicPort;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    @Override
+    public String toString() {
+        return "Port{" +
+                "privatePort=" + privatePort +
+                ", publicPort=" + publicPort +
+                ", type='" + type + '\'' +
+                '}';
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/Ports.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/Ports.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/Ports.java
new file mode 100644
index 0000000..d9fdab6
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/Ports.java
@@ -0,0 +1,131 @@
+package com.kpelykh.docker.client.model;
+
+import org.codehaus.jackson.*;
+import org.codehaus.jackson.map.DeserializationContext;
+import org.codehaus.jackson.map.JsonDeserializer;
+import org.codehaus.jackson.map.JsonSerializer;
+import org.codehaus.jackson.map.SerializerProvider;
+import org.codehaus.jackson.map.annotate.JsonDeserialize;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+import org.codehaus.jackson.node.NullNode;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Created by ben on 16/12/13.
+ */
+@JsonDeserialize(using=Ports.Deserializer.class)
+@JsonSerialize(using=Ports.Serializer.class)
+public class Ports {
+
+
+    private final Map<String, Port> ports = new HashMap<String, Port>();
+
+    public Ports() { }
+
+    public void addPort(Port port) {
+        ports.put(port.getPort(), port);
+    }
+
+    @Override
+    public String toString(){
+        return ports.toString();
+    }
+
+    public Map<String, Port> getAllPorts(){
+        return ports;
+    }
+
+    public static class Port{
+
+        private final String scheme;
+        private final String port;
+        private final String hostIp;
+        private final String hostPort;
+
+        public Port(String scheme_, String port_, String hostIp_, String hostPort_) {
+            scheme = scheme_;
+            port = port_;
+            hostIp = hostIp_;
+            hostPort = hostPort_;
+        }
+
+        public String getScheme() {
+            return scheme;
+        }
+
+        public String getPort() {
+            return port;
+        }
+
+        public String getHostIp() {
+            return hostIp;
+        }
+
+        public String getHostPort() {
+            return hostPort;
+        }
+
+        public static Port makePort(String full, String hostIp, String hostPort) {
+            if (full == null) return null;
+            String[] pieces = full.split("/");
+            return new Port(pieces[1], pieces[0], hostIp, hostPort);
+        }
+
+        @Override
+        public String toString() {
+            return "Port{" +
+                    "scheme='" + scheme + '\'' +
+                    ", port='" + port + '\'' +
+                    ", hostIp='" + hostIp + '\'' +
+                    ", hostPort='" + hostPort + '\'' +
+                    '}';
+        }
+    }
+
+    public static class Deserializer extends JsonDeserializer<Ports> {
+        @Override
+        public Ports deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+
+            Ports out = new Ports();
+            ObjectCodec oc = jsonParser.getCodec();
+            JsonNode node = oc.readTree(jsonParser);
+            for (Iterator<Map.Entry<String, JsonNode>> it = node.getFields(); it.hasNext();) {
+
+                Map.Entry<String, JsonNode> field = it.next();
+                if (!field.getValue().equals(NullNode.getInstance())) {
+                    String hostIp = field.getValue().get(0).get("HostIp").getTextValue();
+                    String hostPort = field.getValue().get(0).get("HostPort").getTextValue();
+                    out.addPort(Port.makePort(field.getKey(), hostIp, hostPort));
+                }
+            }
+            return out;
+        }
+    }
+
+    public static class Serializer extends JsonSerializer<Ports> {
+
+        @Override
+        public void serialize(Ports ports, JsonGenerator jsonGen,
+                              SerializerProvider serProvider) throws IOException, JsonProcessingException {
+
+            jsonGen.writeStartObject();//{
+            for(String portKey : ports.getAllPorts().keySet()){
+                Port p = ports.getAllPorts().get(portKey);
+                jsonGen.writeFieldName(p.getPort() + "/" + p.getScheme());
+                jsonGen.writeStartArray();
+                jsonGen.writeStartObject();
+                jsonGen.writeStringField("HostIp", p.hostIp);
+                jsonGen.writeStringField("HostPort", p.hostPort);
+                jsonGen.writeEndObject();
+                jsonGen.writeEndArray();
+            }
+            jsonGen.writeEndObject();//}
+        }
+
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/SearchItem.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/SearchItem.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/SearchItem.java
new file mode 100644
index 0000000..9c0942e
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/SearchItem.java
@@ -0,0 +1,52 @@
+package com.kpelykh.docker.client.model;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ *
+ * @author Konstantin Pelykh (kpelykh@gmail.com)
+ *
+ */
+public class SearchItem {
+
+    @JsonProperty("star_count")
+    private int starCount;
+
+    @JsonProperty("is_official")
+    private boolean isOfficial;
+
+    @JsonProperty("is_trusted")
+    private boolean isTrusted;
+
+    @JsonProperty("name")
+    private String name;
+
+    @JsonProperty("description")
+    private String description;
+
+    public int getStarCount() {
+        return starCount;
+    }
+
+    public boolean isOfficial() {
+        return isOfficial;
+    }
+
+    public boolean isTrusted() {
+        return isTrusted;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public String toString() {
+        return  "name='" + name + '\'' +
+                ", description='" + description + '\'' + '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/model/Version.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/model/Version.java b/docker-java/src/main/java/com/kpelykh/docker/client/model/Version.java
new file mode 100644
index 0000000..915ae67
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/model/Version.java
@@ -0,0 +1,91 @@
+package com.kpelykh.docker.client.model;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ *
+ * @author Konstantin Pelykh (kpelykh@gmail.com)
+ *
+ */
+public class Version {
+
+
+    @JsonProperty("Version")
+    private String version;
+
+    @JsonProperty("GitCommit")
+    private String  gitCommit;
+
+    @JsonProperty("GoVersion")
+    private String  goVersion;
+    
+    @JsonProperty("KernelVersion")
+    private String kernelVersion;
+
+    @JsonProperty("Arch")
+    private String  arch;
+
+    @JsonProperty("Os")
+    private String operatingSystem;
+
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public String getGitCommit() {
+        return gitCommit;
+    }
+
+    public void setGitCommit(String gitCommit) {
+        this.gitCommit = gitCommit;
+    }
+
+    public String getGoVersion() {
+        return goVersion;
+    }
+
+    public void setGoVersion(String goVersion) {
+        this.goVersion = goVersion;
+    }
+
+    public String getKernelVersion() {
+        return kernelVersion;
+    }
+
+    public void setKernelVersion(String kernelVersion) {
+        this.kernelVersion = kernelVersion;
+    }
+
+    public String getArch() {
+        return arch;
+    }
+
+    public void setArch(String arch) {
+        this.arch = arch;
+    }
+
+    public String getOperatingSystem() {
+        return operatingSystem;
+    }
+
+    public void setOperatingSystem(String operatingSystem) {
+        this.operatingSystem = operatingSystem;
+    }
+
+    @Override
+    public String toString() {
+        return "Version{" +
+                "version='" + version + '\'' +
+                ", gitCommit='" + gitCommit + '\'' +
+                ", goVersion='" + goVersion + '\'' +
+                ", kernelVersion='" + kernelVersion + '\'' +
+                ", arch='" + arch + '\'' +
+                ", operatingSystem='" + operatingSystem + '\'' +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/utils/CompressArchiveUtil.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/utils/CompressArchiveUtil.java b/docker-java/src/main/java/com/kpelykh/docker/client/utils/CompressArchiveUtil.java
new file mode 100644
index 0000000..502ad0b
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/utils/CompressArchiveUtil.java
@@ -0,0 +1,59 @@
+package com.kpelykh.docker.client.utils;
+
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.filefilter.RegexFileFilter;
+import org.apache.commons.lang.StringUtils;
+
+import java.io.*;
+import java.util.Collection;
+
+import static org.apache.commons.io.filefilter.FileFilterUtils.*;
+
+public class CompressArchiveUtil {
+
+	public static File archiveTARFiles(File baseDir, String archiveNameWithOutExtension) throws IOException {
+
+		File tarFile = null;
+		
+        tarFile = new File(FileUtils.getTempDirectoryPath(), archiveNameWithOutExtension + ".tar");
+
+        Collection<File> files =
+                FileUtils.listFiles(
+                        baseDir,
+                        new RegexFileFilter("^(.*?)"),
+                        and(directoryFileFilter(), notFileFilter(nameFileFilter(baseDir.getName()))));
+
+        byte[] buf = new byte[1024];
+        int len;
+
+        {
+            TarArchiveOutputStream tos = new TarArchiveOutputStream(new FileOutputStream(tarFile));
+            tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
+            for (File file : files) {
+                TarArchiveEntry tarEntry = new TarArchiveEntry(file);
+                tarEntry.setName(StringUtils.substringAfter(file.toString(), baseDir.getPath()));
+
+                tos.putArchiveEntry(tarEntry);
+
+                if (!file.isDirectory()) {
+                    FileInputStream fin = new FileInputStream(file);
+                    BufferedInputStream in = new BufferedInputStream(fin);
+
+                    while ((len = in.read(buf)) != -1) {
+                        tos.write(buf, 0, len);
+                    }
+
+                    in.close();
+                }
+                tos.closeArchiveEntry();
+
+            }
+            tos.close();
+        }
+
+		
+		return tarFile;
+	}
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/main/java/com/kpelykh/docker/client/utils/JsonClientFilter.java
----------------------------------------------------------------------
diff --git a/docker-java/src/main/java/com/kpelykh/docker/client/utils/JsonClientFilter.java b/docker-java/src/main/java/com/kpelykh/docker/client/utils/JsonClientFilter.java
new file mode 100644
index 0000000..55b8b28
--- /dev/null
+++ b/docker-java/src/main/java/com/kpelykh/docker/client/utils/JsonClientFilter.java
@@ -0,0 +1,26 @@
+package com.kpelykh.docker.client.utils;
+
+
+import com.sun.jersey.api.client.ClientRequest;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.filter.ClientFilter;
+
+/**
+ *
+ * @author Konstantin Pelykh (kpelykh@gmail.com)
+ *
+ */
+public class JsonClientFilter extends ClientFilter {
+
+    public ClientResponse handle(ClientRequest cr) {
+        // Call the next filter
+        ClientResponse resp = getNext().handle(cr);
+        String respContentType = resp.getHeaders().getFirst("Content-Type");
+        if (respContentType.startsWith("text/plain")) {
+            String newContentType = "application/json" + respContentType.substring(10);
+            resp.getHeaders().putSingle("Content-Type", newContentType);
+        }
+        return resp;
+    }
+
+}


[5/7] git commit: updated refs/heads/docker to 2ab7524

Posted by tu...@apache.org.
fix building


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/234831a9
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/234831a9
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/234831a9

Branch: refs/heads/docker
Commit: 234831a996aa501f8f8643926224318c6875e2d7
Parents: cd8a452
Author: tuna <ng...@gmail.com>
Authored: Sat Mar 29 01:40:37 2014 +0700
Committer: tuna <ng...@gmail.com>
Committed: Sat Mar 29 15:26:54 2014 +0700

----------------------------------------------------------------------
 engine/schema/src/com/cloud/upgrade/dao/Upgrade421to430.java   | 2 +-
 plugins/pom.xml                                                | 1 +
 server/src/com/cloud/hypervisor/DockerGuru.java                | 4 ++--
 .../hypervisor/kvm/discoverer/DockerServerDiscoverer.java      | 2 +-
 .../cloud/network/router/VirtualNetworkApplianceManager.java   | 2 +-
 setup/db/db/schema-410to420.sql                                | 6 ++----
 6 files changed, 8 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/234831a9/engine/schema/src/com/cloud/upgrade/dao/Upgrade421to430.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade421to430.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade421to430.java
index 7da2863..bdf2d9e 100755
--- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade421to430.java
+++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade421to430.java
@@ -213,7 +213,7 @@ public class Upgrade421to430 implements DbUpgrade {
                         case LXC:       hypervisorsListInUse.add(Hypervisor.HypervisorType.LXC);
                             break;
                         case Docker:    hypervisorsListInUse.add(Hypervisor.HypervisorType.Docker);
-                        	break;
+                            break;
                     }
                 }
             } catch (SQLException e) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/234831a9/plugins/pom.xml
----------------------------------------------------------------------
diff --git a/plugins/pom.xml b/plugins/pom.xml
index 4f7805a..86308bc 100755
--- a/plugins/pom.xml
+++ b/plugins/pom.xml
@@ -46,6 +46,7 @@
     <module>network-elements/ovs</module>
     <module>network-elements/juniper-contrail</module>
     <module>network-elements/palo-alto</module>
+    <module>network-elements/netscaler</module>
     <module>network-elements/nicira-nvp</module>
     <module>network-elements/bigswitch-vns</module>
     <module>network-elements/midonet</module>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/234831a9/server/src/com/cloud/hypervisor/DockerGuru.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/hypervisor/DockerGuru.java b/server/src/com/cloud/hypervisor/DockerGuru.java
index bba6927..c8d2d6e 100644
--- a/server/src/com/cloud/hypervisor/DockerGuru.java
+++ b/server/src/com/cloud/hypervisor/DockerGuru.java
@@ -18,7 +18,7 @@ public class DockerGuru extends HypervisorGuruBase implements HypervisorGuru {
     public HypervisorType getHypervisorType() {
         return HypervisorType.Docker;
     }
-    
+
     protected DockerGuru() {
         super();
     }
@@ -33,7 +33,7 @@ public class DockerGuru extends HypervisorGuruBase implements HypervisorGuru {
 
         return to;
     }
-    
+
     @Override
     public boolean trackVmHostChange() {
         return false;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/234831a9/server/src/com/cloud/hypervisor/kvm/discoverer/DockerServerDiscoverer.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/hypervisor/kvm/discoverer/DockerServerDiscoverer.java b/server/src/com/cloud/hypervisor/kvm/discoverer/DockerServerDiscoverer.java
index 558aa25..d7ce7c2 100644
--- a/server/src/com/cloud/hypervisor/kvm/discoverer/DockerServerDiscoverer.java
+++ b/server/src/com/cloud/hypervisor/kvm/discoverer/DockerServerDiscoverer.java
@@ -9,7 +9,7 @@ import com.cloud.resource.Discoverer;
 
 @Local(value = Discoverer.class)
 public class DockerServerDiscoverer extends LibvirtServerDiscoverer {
-	private static final Logger s_logger = Logger.getLogger(DockerServerDiscoverer.class);
+    private static final Logger s_logger = Logger.getLogger(DockerServerDiscoverer.class);
 
     @Override
     public Hypervisor.HypervisorType getHypervisorType() {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/234831a9/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java
index c2f43b8..afbde31 100755
--- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java
+++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java
@@ -50,7 +50,7 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA
     static final String RouterTemplateVmwareCK = "router.template.vmware";
     static final String RouterTemplateHyperVCK = "router.template.hyperv";
     static final String RouterTemplateLxcCK = "router.template.lxc";
-    static final String RouterTemplateDockerCK = "router.template.docker";    
+    static final String RouterTemplateDockerCK = "router.template.docker";
     static final String SetServiceMonitorCK = "network.router.EnableServiceMonitoring";
 
     static final ConfigKey<String> RouterTemplateXen = new ConfigKey<String>(String.class, RouterTemplateXenCK, "Advanced", "SystemVM Template (XenServer)",

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/234831a9/setup/db/db/schema-410to420.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql
index 9af1162..4928b28 100755
--- a/setup/db/db/schema-410to420.sql
+++ b/setup/db/db/schema-410to420.sql
@@ -661,7 +661,7 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Project Defaults', 'DEFAULT'
 ALTER TABLE `cloud`.`remote_access_vpn` ADD COLUMN `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT COMMENT 'id';
 ALTER TABLE `cloud`.`remote_access_vpn` ADD COLUMN `uuid` varchar(40) UNIQUE;
 
--- START: support for LXC and Docker
+-- START: support for LXC
  
 INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(uuid, hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES (UUID(), 'LXC', 'default', 50, 1);
 INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(uuid, hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES (UUID(), 'Docker', 'default', 50, 1);
@@ -673,12 +673,10 @@ UPDATE configuration SET value='KVM,XenServer,VMware,BareMetal,Ovm,LXC,Docker' W
  
 INSERT INTO `cloud`.`vm_template` (id, uuid, 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, UUID(), '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');
-INSERT INTO `cloud`.`vm_template` (id, uuid, 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, UUID(), 'routing-10', 'SystemVM Template (Docker)', 0, now(), 'SYSTEM', 0, 64, 1, 'http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2', '2755de1f9ef2ce4d6f2bee2efbb4da92', 0, 'SystemVM Template (Docker)', 'QCOW2', 15, 0, 1, 'Docker');
 
 ALTER TABLE `cloud`.`user_vm` MODIFY user_data TEXT(32768);
 
--- END: support for LXC and Docker
+-- END: support for LXC
 
 CREATE TABLE `cloud`.`vm_snapshots` (
   `id` bigint(20) unsigned NOT NULL auto_increment COMMENT 'Primary Key',


[2/7] add docker client

Posted by tu...@apache.org.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java
----------------------------------------------------------------------
diff --git a/docker-java/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java b/docker-java/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java
new file mode 100644
index 0000000..46c2d57
--- /dev/null
+++ b/docker-java/src/test/java/com/kpelykh/docker/client/test/DockerClientTest.java
@@ -0,0 +1,791 @@
+package com.kpelykh.docker.client.test;
+
+import com.kpelykh.docker.client.DockerClient;
+import com.kpelykh.docker.client.DockerException;
+import com.kpelykh.docker.client.model.*;
+
+import com.sun.jersey.api.client.ClientResponse;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.LineIterator;
+import org.apache.commons.lang.StringUtils;
+import org.hamcrest.Matcher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.ITestResult;
+import org.testng.annotations.*;
+
+import java.io.*;
+import java.lang.reflect.Method;
+import java.net.DatagramSocket;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.List;
+
+import static ch.lambdaj.Lambda.filter;
+import static ch.lambdaj.Lambda.selectUnique;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
+import static org.hamcrest.Matchers.hasItem;
+import static org.testinfected.hamcrest.jpa.HasFieldWithValue.hasField;
+
+/**
+ * Unit test for DockerClient.
+ * @author Konstantin Pelykh (kpelykh@gmail.com)
+ */
+public class DockerClientTest extends Assert
+{
+    public static final Logger LOG = LoggerFactory.getLogger(DockerClientTest.class);
+
+    private DockerClient dockerClient;
+
+    private List<String> tmpImgs = new ArrayList<String>();
+    private List<String> tmpContainers = new ArrayList<String>();
+
+    @BeforeTest
+    public void beforeTest() throws DockerException {
+        LOG.info("======================= BEFORETEST =======================");
+        String url = System.getProperty("docker.url", "http://192.168.1.188:5555");
+        LOG.info("Connecting to Docker server at " + url);
+        dockerClient = new DockerClient(url);
+        
+        LOG.info("Creating image 'busybox'");
+        dockerClient.pull("busybox");
+
+        assertNotNull(dockerClient);
+        LOG.info("======================= END OF BEFORETEST =======================\n\n");
+    }
+
+    @AfterTest
+    public void afterTest() {
+        LOG.info("======================= END OF AFTERTEST =======================");
+    }
+
+    @BeforeMethod
+    public void beforeMethod(Method method) {
+        LOG.info(String.format("################################## STARTING %s ##################################", method.getName()));
+    }
+
+    @AfterMethod
+    public void afterMethod(ITestResult result) {
+
+        for (String container : tmpContainers) {
+            LOG.info("Cleaning up temporary container {}", container);
+            try {
+             dockerClient.stopContainer(container);
+             dockerClient.kill(container);
+             dockerClient.removeContainer(container);
+            } catch (DockerException ignore) {}
+        }
+
+        for (String image : tmpImgs) {
+            LOG.info("Cleaning up temporary image {}", image);
+            try {
+                dockerClient.removeImage(image);
+            } catch (DockerException ignore) {}
+        }
+
+        LOG.info("################################## END OF {} ##################################\n", result.getName());
+    }
+
+    /*
+     * #########################
+     * ## INFORMATION TESTS ##
+     * #########################
+    */
+
+    @Test
+    public void testDockerVersion() throws DockerException {
+        Version version = dockerClient.version();
+        LOG.info(version.toString());
+
+        assertTrue(version.getGoVersion().length() > 0);
+        assertTrue(version.getVersion().length() > 0);
+
+        assertEquals(StringUtils.split(version.getVersion(), ".").length, 3);
+
+    }
+
+    @Test
+    public void testDockerInfo() throws DockerException {
+        Info dockerInfo = dockerClient.info();
+        LOG.info(dockerInfo.toString());
+
+        assertTrue(dockerInfo.toString().contains("containers"));
+        assertTrue(dockerInfo.toString().contains("images"));
+        assertTrue(dockerInfo.toString().contains("debug"));
+
+        assertTrue(dockerInfo.getContainers() > 0);
+        assertTrue(dockerInfo.getImages() > 0);
+        assertTrue(dockerInfo.getNFd() > 0);
+        assertTrue(dockerInfo.getNGoroutines() > 0);
+        assertTrue(dockerInfo.isMemoryLimit());
+    }
+
+    @Test
+    public void testDockerSearch() throws DockerException {
+        List<SearchItem> dockerSearch = dockerClient.search("busybox");
+        LOG.info("Search returned {}", dockerSearch.toString());
+
+        Matcher matcher = hasItem(hasField("name", equalTo("busybox")));
+        assertThat(dockerSearch, matcher);
+
+        assertThat(filter(hasField("name", is("busybox")), dockerSearch).size(), equalTo(1));
+    }
+
+    /*
+     * ###################
+     * ## LISTING TESTS ##
+     * ###################
+     */
+
+
+    @Test
+    public void testImages() throws DockerException {
+        List<Image> images = dockerClient.getImages(true);
+        assertThat(images, notNullValue());
+        LOG.info("Images List: {}", images);
+        Info info = dockerClient.info();
+
+        assertThat(images.size(), equalTo(info.getImages()));
+
+        Image img = images.get(0);
+        assertThat(img.getCreated(), is(greaterThan(0L)) );
+        assertThat(img.getVirtualSize(), is(greaterThan(0L)) );
+        assertThat(img.getId(), not(isEmptyString()));
+        assertThat(img.getTag(), not(isEmptyString()));
+        assertThat(img.getRepository(), not(isEmptyString()));
+    }
+
+
+    @Test
+    public void testListContainers() throws DockerException {
+        List<Container> containers = dockerClient.listContainers(true);
+        assertThat(containers, notNullValue());
+        LOG.info("Container List: {}", containers);
+
+        int size = containers.size();
+
+        ContainerConfig containerConfig = new ContainerConfig();
+        containerConfig.setImage("busybox");
+        containerConfig.setCmd(new String[]{"echo"});
+
+        ContainerCreateResponse container1 = dockerClient.createContainer(containerConfig);
+        assertThat(container1.getId(), not(isEmptyString()));
+        dockerClient.startContainer(container1.getId());
+        tmpContainers.add(container1.getId());
+
+        List containers2 = dockerClient.listContainers(true);
+        assertThat(size + 1, is(equalTo(containers2.size())));
+        Matcher matcher = hasItem(hasField("id", startsWith(container1.getId())));
+        assertThat(containers2, matcher);
+
+        List<Container> filteredContainers = filter(hasField("id", startsWith(container1.getId())), containers2);
+        assertThat(filteredContainers.size(), is(equalTo(1)));
+
+        Container container2 = filteredContainers.get(0);
+        assertThat(container2.getCommand(), not(isEmptyString()));
+        assertThat(container2.getImage(), equalTo("busybox:latest"));
+    }
+
+
+    /*
+     * #####################
+     * ## CONTAINER TESTS ##
+     * #####################
+     */
+
+    @Test
+    public void testCreateContainer() throws DockerException {
+        ContainerConfig containerConfig = new ContainerConfig();
+        containerConfig.setImage("busybox");
+        containerConfig.setCmd(new String[]{"true"});
+
+
+        ContainerCreateResponse container = dockerClient.createContainer(containerConfig);
+
+        LOG.info("Created container {}", container.toString());
+
+        assertThat(container.getId(), not(isEmptyString()));
+
+        tmpContainers.add(container.getId());
+    }
+
+    @Test
+    public void testStartContainer() throws DockerException {
+
+        ContainerConfig containerConfig = new ContainerConfig();
+        containerConfig.setImage("busybox");
+        containerConfig.setCmd(new String[]{"true"});
+
+        ContainerCreateResponse container = dockerClient.createContainer(containerConfig);
+        LOG.info("Created container {}", container.toString());
+        assertThat(container.getId(), not(isEmptyString()));
+        boolean add = tmpContainers.add(container.getId());
+
+        dockerClient.startContainer(container.getId());
+
+        ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId());
+        LOG.info("Container Inspect: {}", containerInspectResponse.toString());
+
+        assertThat(containerInspectResponse.config, is(notNullValue()));
+        assertThat(containerInspectResponse.getId(), not(isEmptyString()));
+
+        assertThat(containerInspectResponse.getId(), startsWith(container.getId()));
+
+        assertThat(containerInspectResponse.getImage(), not(isEmptyString()));
+        assertThat(containerInspectResponse.getState(), is(notNullValue()));
+
+        assertThat(containerInspectResponse.getState().running, is(true));
+
+        if (!containerInspectResponse.getState().running) {
+            assertThat(containerInspectResponse.getState().exitCode, is(equalTo(0)));
+        }
+
+    }
+
+    @Test
+    public void testWaitContainer() throws DockerException {
+
+        ContainerConfig containerConfig = new ContainerConfig();
+        containerConfig.setImage("busybox");
+        containerConfig.setCmd(new String[]{"true"});
+
+        ContainerCreateResponse container = dockerClient.createContainer(containerConfig);
+        LOG.info("Created container: {}", container.toString());
+        assertThat(container.getId(), not(isEmptyString()));
+        tmpContainers.add(container.getId());
+
+        dockerClient.startContainer(container.getId());
+
+        int exitCode = dockerClient.waitContainer(container.getId());
+        LOG.info("Container exit code: {}", exitCode);
+
+        assertThat(exitCode, equalTo(0));
+
+        ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId());
+        LOG.info("Container Inspect: {}", containerInspectResponse.toString());
+
+        assertThat(containerInspectResponse.getState().running, is(equalTo(false)));
+        assertThat(containerInspectResponse.getState().exitCode, is(equalTo(exitCode)));
+
+    }
+
+    @Test
+    public void testLogs() throws DockerException, IOException {
+
+        String snippet = "hello world";
+
+        ContainerConfig containerConfig = new ContainerConfig();
+        containerConfig.setImage("busybox");
+        containerConfig.setCmd(new String[] {"/bin/echo", snippet});
+
+        ContainerCreateResponse container = dockerClient.createContainer(containerConfig);
+        LOG.info("Created container: {}", container.toString());
+        assertThat(container.getId(), not(isEmptyString()));
+
+        dockerClient.startContainer(container.getId());
+        tmpContainers.add(container.getId());
+
+        int exitCode = dockerClient.waitContainer(container.getId());
+
+        assertThat(exitCode, equalTo(0));
+
+        ClientResponse response = dockerClient.logContainer(container.getId());
+
+        StringWriter logwriter = new StringWriter();
+
+        try {
+            LineIterator itr = IOUtils.lineIterator(response.getEntityInputStream(), "UTF-8");
+            while (itr.hasNext()) {
+                String line = itr.next();
+                logwriter.write(line + (itr.hasNext() ? "\n" : ""));
+                LOG.info(line);
+            }
+        } finally {
+            IOUtils.closeQuietly(response.getEntityInputStream());
+        }
+
+        String fullLog = logwriter.toString();
+
+        LOG.info("Container log: {}", fullLog);
+        assertThat(fullLog, endsWith(snippet));
+    }
+
+    //This test doesn't work in Ubuntu 12.04 due to
+    //Error mounting '/dev/mapper/docker-8:5-...
+    //ref: https://github.com/dotcloud/docker/issues/4036
+
+    @Test
+    public void testDiff() throws DockerException {
+        ContainerConfig containerConfig = new ContainerConfig();
+        containerConfig.setImage("busybox");
+        containerConfig.setCmd(new String[] {"touch", "/test"});
+
+        ContainerCreateResponse container = dockerClient.createContainer(containerConfig);
+        LOG.info("Created container: {}", container.toString());
+        assertThat(container.getId(), not(isEmptyString()));
+        dockerClient.startContainer(container.getId());
+        boolean add = tmpContainers.add(container.getId());
+        int exitCode = dockerClient.waitContainer(container.getId());
+        assertThat(exitCode, equalTo(0));
+
+        List filesystemDiff = dockerClient.containterDiff(container.getId());
+        LOG.info("Container DIFF: {}", filesystemDiff.toString());
+
+        assertThat(filesystemDiff.size(), equalTo(1));
+        ChangeLog testChangeLog = selectUnique(filesystemDiff, hasField("path", equalTo("/test")));
+
+        assertThat(testChangeLog, hasField("path", equalTo("/test")));
+        assertThat(testChangeLog, hasField("kind", equalTo(1)));
+    }
+
+    @Test
+    public void testStopContainer() throws DockerException {
+
+        ContainerConfig containerConfig = new ContainerConfig();
+        containerConfig.setImage("busybox");
+        containerConfig.setCmd(new String[] {"sleep", "9999"});
+
+        ContainerCreateResponse container = dockerClient.createContainer(containerConfig);
+        LOG.info("Created container: {}", container.toString());
+        assertThat(container.getId(), not(isEmptyString()));
+        dockerClient.startContainer(container.getId());
+        tmpContainers.add(container.getId());
+
+        LOG.info("Stopping container: {}", container.getId());
+        dockerClient.stopContainer(container.getId(), 2);
+
+        ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId());
+        LOG.info("Container Inspect: {}", containerInspectResponse.toString());
+
+        assertThat(containerInspectResponse.getState().running, is(equalTo(false)));
+        assertThat(containerInspectResponse.getState().exitCode, not(equalTo(0)));
+    }
+
+    @Test
+    public void testKillContainer() throws DockerException {
+
+        ContainerConfig containerConfig = new ContainerConfig();
+        containerConfig.setImage("busybox");
+        containerConfig.setCmd(new String[] {"sleep", "9999"});
+
+        ContainerCreateResponse container = dockerClient.createContainer(containerConfig);
+        LOG.info("Created container: {}", container.toString());
+        assertThat(container.getId(), not(isEmptyString()));
+        dockerClient.startContainer(container.getId());
+        tmpContainers.add(container.getId());
+
+        LOG.info("Killing container: {}", container.getId());
+        dockerClient.kill(container.getId());
+
+        ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId());
+        LOG.info("Container Inspect: {}", containerInspectResponse.toString());
+
+        assertThat(containerInspectResponse.getState().running, is(equalTo(false)));
+        assertThat(containerInspectResponse.getState().exitCode, not(equalTo(0)));
+
+    }
+
+    @Test
+    public void restartContainer() throws DockerException {
+
+        ContainerConfig containerConfig = new ContainerConfig();
+        containerConfig.setImage("busybox");
+        containerConfig.setCmd(new String[] {"sleep", "9999"});
+
+        ContainerCreateResponse container = dockerClient.createContainer(containerConfig);
+        LOG.info("Created container: {}", container.toString());
+        assertThat(container.getId(), not(isEmptyString()));
+        dockerClient.startContainer(container.getId());
+        tmpContainers.add(container.getId());
+
+        ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId());
+        LOG.info("Container Inspect: {}",  containerInspectResponse.toString());
+
+        String startTime = containerInspectResponse.getState().startedAt;
+
+        dockerClient.restart(container.getId(), 2);
+
+        ContainerInspectResponse containerInspectResponse2 = dockerClient.inspectContainer(container.getId());
+        LOG.info("Container Inspect After Restart: {}", containerInspectResponse2.toString());
+
+        String startTime2 = containerInspectResponse2.getState().startedAt;
+
+        assertThat(startTime, not(equalTo(startTime2)));
+
+        assertThat(containerInspectResponse.getState().running, is(equalTo(true)));
+
+        dockerClient.kill(container.getId());
+    }
+
+    @Test
+    public void removeContainer() throws DockerException {
+
+        ContainerConfig containerConfig = new ContainerConfig();
+        containerConfig.setImage("busybox");
+        containerConfig.setCmd(new String[] {"true"});
+
+        ContainerCreateResponse container = dockerClient.createContainer(containerConfig);
+
+        dockerClient.startContainer(container.getId());
+        dockerClient.waitContainer(container.getId());
+        tmpContainers.add(container.getId());
+
+        LOG.info("Removing container: {}", container.getId());
+        dockerClient.removeContainer(container.getId());
+
+        List containers2 = dockerClient.listContainers(true);
+        Matcher matcher = not(hasItem(hasField("id", startsWith(container.getId()))));
+        assertThat(containers2, matcher);
+
+    }
+
+    /*
+     * ##################
+     * ## IMAGES TESTS ##
+     * ##################
+     * */
+
+    @Test
+    public void testPullImage() throws DockerException, IOException {
+
+        String testImage = "centos";
+
+        LOG.info("Removing image: {}", testImage);
+        dockerClient.removeImage(testImage);
+
+        Info info = dockerClient.info();
+        LOG.info("Client info: {}", info.toString());
+
+        int imgCount= info.getImages();
+
+        LOG.info("Pulling image: {}", testImage);
+
+        ClientResponse response = dockerClient.pull(testImage);
+
+        StringWriter logwriter = new StringWriter();
+
+        try {
+            LineIterator itr = IOUtils.lineIterator(response.getEntityInputStream(), "UTF-8");
+            while (itr.hasNext()) {
+                String line = itr.next();
+                logwriter.write(line + "\n");
+                LOG.info(line);
+            }
+        } finally {
+            IOUtils.closeQuietly(response.getEntityInputStream());
+        }
+
+        String fullLog = logwriter.toString();
+        assertThat(fullLog, containsString("Download complete"));
+
+        tmpImgs.add(testImage);
+
+        info = dockerClient.info();
+        LOG.info("Client info after pull, {}", info.toString());
+
+        assertThat(imgCount, lessThan(info.getImages()));
+
+        ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(testImage);
+        LOG.info("Image Inspect: {}", imageInspectResponse.toString());
+        assertThat(imageInspectResponse, notNullValue());
+    }
+
+    //This test doesn't work in Ubuntu 12.04 due to
+    //Error mounting '/dev/mapper/docker-8:5-...
+    //ref: https://github.com/dotcloud/docker/issues/4036
+
+    @Test
+    public void commitImage() throws DockerException {
+
+        ContainerConfig containerConfig = new ContainerConfig();
+        containerConfig.setImage("busybox");
+        containerConfig.setCmd(new String[] {"touch", "/test"});
+
+        ContainerCreateResponse container = dockerClient.createContainer(containerConfig);
+        LOG.info("Created container: {}", container.toString());
+        assertThat(container.getId(), not(isEmptyString()));
+        dockerClient.startContainer(container.getId());
+        tmpContainers.add(container.getId());
+
+        LOG.info("Commiting container: {}", container.toString());
+        String imageId = dockerClient.commit(new CommitConfig(container.getId()));
+        tmpImgs.add(imageId);
+
+        ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(imageId);
+        LOG.info("Image Inspect: {}", imageInspectResponse.toString());
+
+        assertThat(imageInspectResponse, hasField("container", startsWith(container.getId())));
+        assertThat(imageInspectResponse.getContainerConfig().getImage(), equalTo("busybox"));
+
+        ImageInspectResponse busyboxImg = dockerClient.inspectImage("busybox");
+
+        assertThat(imageInspectResponse.getParent(), equalTo(busyboxImg.getId()));
+    }
+
+    @Test
+    public void testRemoveImage() throws DockerException, InterruptedException {
+
+
+        ContainerConfig containerConfig = new ContainerConfig();
+        containerConfig.setImage("busybox");
+        containerConfig.setCmd(new String[] {"touch", "/test"});
+
+        ContainerCreateResponse container = dockerClient.createContainer(containerConfig);
+        LOG.info("Created container: {}", container.toString());
+        assertThat(container.getId(), not(isEmptyString()));
+        dockerClient.startContainer(container.getId());
+        tmpContainers.add(container.getId());
+
+        LOG.info("Commiting container {}", container.toString());
+        String imageId = dockerClient.commit(new CommitConfig(container.getId()));
+        tmpImgs.add(imageId);
+
+        dockerClient.stopContainer(container.getId());
+        dockerClient.kill(container.getId());
+        dockerClient.removeContainer(container.getId());
+
+        tmpContainers.remove(container.getId());
+        LOG.info("Removing image: {}", imageId);
+        dockerClient.removeImage(imageId);
+
+        List containers = dockerClient.listContainers(true);
+        Matcher matcher = not(hasItem(hasField("id", startsWith(imageId))));
+        assertThat(containers, matcher);
+    }
+
+
+    /*
+     *
+     * ################
+     * ## MISC TESTS ##
+     * ################
+     */
+
+    @Test
+    public void testRunShlex() throws DockerException {
+
+        String[] commands = new String[] {
+                "true",
+                "echo \"The Young Descendant of Tepes & Septette for the Dead Princess\"",
+                "echo -n 'The Young Descendant of Tepes & Septette for the Dead Princess'",
+                "/bin/sh -c echo Hello World",
+                "/bin/sh -c echo 'Hello World'",
+                "echo 'Night of Nights'",
+                "true && echo 'Night of Nights'"
+        };
+
+        for (String command : commands) {
+            LOG.info("Running command: [{}]",  command);
+
+            ContainerConfig containerConfig = new ContainerConfig();
+            containerConfig.setImage("busybox");
+            containerConfig.setCmd( commands );
+
+            ContainerCreateResponse container = dockerClient.createContainer(containerConfig);
+            dockerClient.startContainer(container.getId());
+            tmpContainers.add(container.getId());
+            int exitcode = dockerClient.waitContainer(container.getId());
+            assertThat(exitcode, equalTo(0));
+        }
+    }
+
+
+    @Test
+    public void testNginxDockerfileBuilder() throws DockerException, IOException {
+        File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("nginx").getFile());
+
+        ClientResponse response = dockerClient.build(baseDir);
+
+        StringWriter logwriter = new StringWriter();
+
+        try {
+            LineIterator itr = IOUtils.lineIterator(response.getEntityInputStream(), "UTF-8");
+            while (itr.hasNext()) {
+                String line = itr.next();
+                logwriter.write(line + "\n");
+                LOG.info(line);
+            }
+        } finally {
+            IOUtils.closeQuietly(response.getEntityInputStream());
+        }
+
+        String fullLog = logwriter.toString();
+        assertThat(fullLog, containsString("Successfully built"));
+
+        String imageId = StringUtils.substringBetween(fullLog, "Successfully built ", "\\n\"}").trim();
+
+        ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(imageId);
+        assertThat(imageInspectResponse, not(nullValue()));
+        LOG.info("Image Inspect: {}", imageInspectResponse.toString());
+        tmpImgs.add(imageInspectResponse.getId());
+
+        assertThat(imageInspectResponse.getAuthor(), equalTo("Guillaume J. Charmes \"guillaume@dotcloud.com\""));
+    }
+
+    @Test
+    public void testDockerBuilderAddFile() throws DockerException, IOException {
+        File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddFile").getFile());
+        dockerfileBuild(baseDir, "Successfully executed testrun.sh");
+    }
+
+    @Test
+    public void testDockerBuilderAddFolder() throws DockerException, IOException {
+        File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("testAddFolder").getFile());
+        dockerfileBuild(baseDir, "Successfully executed testAddFolder.sh");
+    }
+
+    @Test
+    public void testImportImageFromTar() throws DockerException, IOException {
+        InputStream tar = Thread.currentThread().getContextClassLoader().getResourceAsStream("testImportImageFromTar/empty.tar");
+        String imageId = dockerClient.importImage("empty", null, tar).getId();
+        assert imageId.contains(dockerClient.inspectImage("empty").getId());
+    }
+
+    @Test
+    public void testNetCatDockerfileBuilder() throws DockerException, IOException, InterruptedException {
+        File baseDir = new File(Thread.currentThread().getContextClassLoader().getResource("netcat").getFile());
+
+        ClientResponse response = dockerClient.build(baseDir);
+
+        StringWriter logwriter = new StringWriter();
+
+        try {
+            LineIterator itr = IOUtils.lineIterator(response.getEntityInputStream(), "UTF-8");
+            while (itr.hasNext()) {
+                String line = itr.next();
+                logwriter.write(line + "\n");
+                LOG.info(line);
+            }
+        } finally {
+            IOUtils.closeQuietly(response.getEntityInputStream());
+        }
+
+        String fullLog = logwriter.toString();
+        assertThat(fullLog, containsString("Successfully built"));
+
+        String imageId = StringUtils.substringBetween(fullLog, "Successfully built ", "\\n\"}").trim();
+
+        ImageInspectResponse imageInspectResponse = dockerClient.inspectImage(imageId);
+        assertThat(imageInspectResponse, not(nullValue()));
+        LOG.info("Image Inspect: {}", imageInspectResponse.toString());
+        tmpImgs.add(imageInspectResponse.getId());
+
+        ContainerConfig containerConfig = new ContainerConfig();
+        containerConfig.setImage(imageInspectResponse.getId());
+        ContainerCreateResponse container = dockerClient.createContainer(containerConfig);
+        assertThat(container.getId(), not(isEmptyString()));
+        dockerClient.startContainer(container.getId());
+        tmpContainers.add(container.getId());
+
+        ContainerInspectResponse containerInspectResponse = dockerClient.inspectContainer(container.getId());
+
+        assertThat(containerInspectResponse.getId(), notNullValue());
+        assertThat(containerInspectResponse.getNetworkSettings().ports, notNullValue());
+
+        //No use as such if not running on the server
+        for(String portstr : containerInspectResponse.getNetworkSettings().ports.getAllPorts().keySet()){
+
+         Ports.Port p = containerInspectResponse.getNetworkSettings().ports.getAllPorts().get(portstr);
+         int port = Integer.valueOf(p.getHostPort());
+         LOG.info("Checking port {} is open", port);
+             assertThat(available(port), is(false));
+        }
+        dockerClient.stopContainer(container.getId(), 0);
+
+    }
+
+
+    // UTIL
+
+    /**
+     * Checks to see if a specific port is available.
+     *
+     * @param port the port to check for availability
+     */
+    public static boolean available(int port) {
+        if (port < 1100 || port > 60000) {
+            throw new IllegalArgumentException("Invalid start port: " + port);
+        }
+
+        ServerSocket ss = null;
+        DatagramSocket ds = null;
+        try {
+            ss = new ServerSocket(port);
+            ss.setReuseAddress(true);
+            ds = new DatagramSocket(port);
+            ds.setReuseAddress(true);
+            return true;
+        } catch (IOException e) {
+        } finally {
+            if (ds != null) {
+                ds.close();
+            }
+
+            if (ss != null) {
+                try {
+                    ss.close();
+                } catch (IOException e) {
+                /* should not be thrown */
+                }
+            }
+        }
+
+        return false;
+    }
+
+    private void dockerfileBuild(File baseDir, String expectedText) throws DockerException, IOException {
+
+        //Build image
+        ClientResponse response = dockerClient.build(baseDir);
+
+        StringWriter logwriter = new StringWriter();
+
+        try {
+            LineIterator itr = IOUtils.lineIterator(response.getEntityInputStream(), "UTF-8");
+            while (itr.hasNext()) {
+                String line = itr.next();
+                logwriter.write(line + "\n");
+                LOG.info(line);
+            }
+        } finally {
+            IOUtils.closeQuietly(response.getEntityInputStream());
+        }
+
+        String fullLog = logwriter.toString();
+        assertThat(fullLog, containsString("Successfully built"));
+
+        String imageId = StringUtils.substringBetween(fullLog, "Successfully built ", "\\n\"}").trim();
+
+        //Create container based on image
+        ContainerConfig containerConfig = new ContainerConfig();
+        containerConfig.setImage(imageId);
+        ContainerCreateResponse container = dockerClient.createContainer(containerConfig);
+        LOG.info("Created container: {}", container.toString());
+        assertThat(container.getId(), not(isEmptyString()));
+
+        dockerClient.startContainer(container.getId());
+        dockerClient.waitContainer(container.getId());
+
+        tmpContainers.add(container.getId());
+
+        //Log container
+        ClientResponse logResponse = dockerClient.logContainer(container.getId());
+
+        StringWriter logwriter2 = new StringWriter();
+
+        try {
+            LineIterator itr = IOUtils.lineIterator(logResponse.getEntityInputStream(), "UTF-8");
+            while (itr.hasNext()) {
+                String line = itr.next();
+                logwriter2.write(line + (itr.hasNext() ? "\n" : ""));
+                LOG.info(line);
+            }
+        } finally {
+            IOUtils.closeQuietly(logResponse.getEntityInputStream());
+        }
+
+        assertThat(logwriter2.toString(), endsWith(expectedText));
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/test/resources/logback.xml
----------------------------------------------------------------------
diff --git a/docker-java/src/test/resources/logback.xml b/docker-java/src/test/resources/logback.xml
new file mode 100644
index 0000000..99f8b3d
--- /dev/null
+++ b/docker-java/src/test/resources/logback.xml
@@ -0,0 +1,16 @@
+<configuration debug="true"> <!-- This will give you some valuable info about logback config upon runtime. Remove this for production. -->
+
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <logger name="com.kpelykh.docker.client" level="TRACE"/>
+    <logger name="com.kpelykh.docker.client.test" level="DEBUG"/>
+
+    <root level="info">
+        <appender-ref ref="STDOUT" />
+    </root>
+
+</configuration>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/test/resources/netcat/Dockerfile
----------------------------------------------------------------------
diff --git a/docker-java/src/test/resources/netcat/Dockerfile b/docker-java/src/test/resources/netcat/Dockerfile
new file mode 100644
index 0000000..1ea3554
--- /dev/null
+++ b/docker-java/src/test/resources/netcat/Dockerfile
@@ -0,0 +1,11 @@
+# Firefox over VNC
+#
+# VERSION               0.3
+
+FROM ubuntu
+
+#install netcat
+RUN apt-get install -y netcat
+
+EXPOSE 6900
+CMD    ["nc", "-l", "6900"]
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/test/resources/nginx/Dockerfile
----------------------------------------------------------------------
diff --git a/docker-java/src/test/resources/nginx/Dockerfile b/docker-java/src/test/resources/nginx/Dockerfile
new file mode 100644
index 0000000..b0abcd6
--- /dev/null
+++ b/docker-java/src/test/resources/nginx/Dockerfile
@@ -0,0 +1,12 @@
+# Nginx
+#
+# VERSION               0.0.1
+
+FROM      ubuntu
+MAINTAINER Guillaume J. Charmes "guillaume@dotcloud.com"
+
+# make sure the package repository is up to date
+RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
+RUN apt-get update
+
+RUN apt-get install -y inotify-tools nginx apache2 openssh-server
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/test/resources/testAddFile/Dockerfile
----------------------------------------------------------------------
diff --git a/docker-java/src/test/resources/testAddFile/Dockerfile b/docker-java/src/test/resources/testAddFile/Dockerfile
new file mode 100644
index 0000000..38afcdd
--- /dev/null
+++ b/docker-java/src/test/resources/testAddFile/Dockerfile
@@ -0,0 +1,9 @@
+FROM      ubuntu
+
+# Copy testrun.sh files into the container
+
+ADD ./testrun.sh    /tmp/
+
+run cp /tmp/testrun.sh /usr/local/bin/ && chmod +x /usr/local/bin/testrun.sh
+
+CMD ["testrun.sh"]

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/test/resources/testAddFile/testrun.sh
----------------------------------------------------------------------
diff --git a/docker-java/src/test/resources/testAddFile/testrun.sh b/docker-java/src/test/resources/testAddFile/testrun.sh
new file mode 100755
index 0000000..80b468e
--- /dev/null
+++ b/docker-java/src/test/resources/testAddFile/testrun.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+echo "Successfully executed testrun.sh"

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/test/resources/testAddFolder/Dockerfile
----------------------------------------------------------------------
diff --git a/docker-java/src/test/resources/testAddFolder/Dockerfile b/docker-java/src/test/resources/testAddFolder/Dockerfile
new file mode 100644
index 0000000..b2a8e2a
--- /dev/null
+++ b/docker-java/src/test/resources/testAddFolder/Dockerfile
@@ -0,0 +1,11 @@
+FROM      ubuntu
+
+# Copy testrun.sh files into the container
+
+ADD .   /src/
+
+run ls -la /src
+
+run cp /src/folderA/testAddFolder.sh /usr/local/bin/ && chmod +x /usr/local/bin/testAddFolder.sh
+
+CMD ["testAddFolder.sh"]

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/test/resources/testAddFolder/folderA/testAddFolder.sh
----------------------------------------------------------------------
diff --git a/docker-java/src/test/resources/testAddFolder/folderA/testAddFolder.sh b/docker-java/src/test/resources/testAddFolder/folderA/testAddFolder.sh
new file mode 100644
index 0000000..3013d92
--- /dev/null
+++ b/docker-java/src/test/resources/testAddFolder/folderA/testAddFolder.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+echo "Successfully executed testAddFolder.sh"

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/docker-java/src/test/resources/testImportImageFromTar/empty.tar
----------------------------------------------------------------------
diff --git a/docker-java/src/test/resources/testImportImageFromTar/empty.tar b/docker-java/src/test/resources/testImportImageFromTar/empty.tar
new file mode 100644
index 0000000..b055b9c
Binary files /dev/null and b/docker-java/src/test/resources/testImportImageFromTar/empty.tar differ

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/cd8a4520/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index ac89c31..e196a59 100644
--- a/pom.xml
+++ b/pom.xml
@@ -427,6 +427,11 @@
       <artifactId>javax.inject</artifactId>
       <version>1</version>
     </dependency>
+    <dependency>
+      <groupId>com.kpelykh</groupId>
+      <artifactId>docker-java</artifactId>
+      <version>0.8.2-SNAPSHOT</version>
+    </dependency>
   </dependencies>
 
   <build>


[6/7] git commit: updated refs/heads/docker to 2ab7524

Posted by tu...@apache.org.
add register Docker template


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/01821512
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/01821512
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/01821512

Branch: refs/heads/docker
Commit: 018215125b05f9e7c6a40ca2bdba612398f4d82b
Parents: 234831a
Author: tuna <ng...@gmail.com>
Authored: Sat Mar 29 14:16:02 2014 +0700
Committer: tuna <ng...@gmail.com>
Committed: Sat Mar 29 15:28:38 2014 +0700

----------------------------------------------------------------------
 .../template/HypervisorTemplateAdapter.java     | 29 +++++++++++++-------
 1 file changed, 19 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/01821512/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 258528a..32f1287 100755
--- a/server/src/com/cloud/template/HypervisorTemplateAdapter.java
+++ b/server/src/com/cloud/template/HypervisorTemplateAdapter.java
@@ -28,7 +28,6 @@ import javax.ejb.Local;
 import javax.inject.Inject;
 
 import org.apache.log4j.Logger;
-
 import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
 import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
 import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd;
@@ -58,6 +57,8 @@ import com.cloud.event.EventTypes;
 import com.cloud.event.UsageEventUtils;
 import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.exception.ResourceAllocationException;
+import com.cloud.hypervisor.Hypervisor;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.org.Grouping;
 import com.cloud.storage.ScopeType;
 import com.cloud.storage.Storage.ImageFormat;
@@ -126,17 +127,20 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
             throw new InvalidParameterValueException("Please specify a valid URL. URL:" + url + " is invalid");
         }
 
-        try {
-            checkFormat(cmd.getFormat(), url);
-        } catch (InvalidParameterValueException ex) {
-            checkFormat(cmd.getFormat(), path);
-        }
+//        Don't check with Docker template
+        if (!cmd.getHypervisor().equals(Hypervisor.HypervisorType.Docker)) {
+            try {
+                checkFormat(cmd.getFormat(), url);
+            } catch (InvalidParameterValueException ex) {
+                checkFormat(cmd.getFormat(), path);
+            }
 
-        UriUtils.validateUrl(url);
+            UriUtils.validateUrl(url);
+            // 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);
-        // Check that the resource limit for secondary storage won't be exceeded
-        _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(cmd.getEntityOwnerId()),
-                ResourceType.secondary_storage, UriUtils.getRemoteSize(url));
         return profile;
     }
 
@@ -183,6 +187,11 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
             throw new CloudRuntimeException("Unable to persist the template " + profile.getTemplate());
         }
 
+        //skip the rest in case of Docker
+        if (profile.getHypervisorType().equals(HypervisorType.Docker)) {
+            return template;
+        }
+
         // find all eligible image stores for this zone scope
         List<DataStore> imageStores = storeMgr.getImageStoresByScope(new ZoneScope(profile.getZoneId()));
         if ( imageStores == null || imageStores.size() == 0 ){