You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mc...@apache.org on 2014/03/13 19:06:13 UTC

[26/50] [abbrv] git commit: updated refs/heads/rbac to 99bdc8d

CLOUDSTACK-4760 : Enabling GPU support for XenServer.
CLOUDSTACK-4762 : Enabling VGPU support for XenServer.

This feature is to enable the GPU-passthrough and vGPU functionality,
with the help of this feature, admins/users will be able to leverage
the GPU graphics unit power by deploying a virtul machine with GPU or
vGPU support or by changing the service offering of an existing VM
at any later point of time. There GPU/vGPU enabled VMs are able to run
graphical applications.
For now, this feature is only supported with XenServer hypervisor but
can be extended to add the support of other hypervisors.


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

Branch: refs/heads/rbac
Commit: c7d31fe288b13ff4f0f046f83f9eb4a9c2bf06c5
Parents: 540d020
Author: Sanjay Tripathi <sa...@citrix.com>
Authored: Thu Feb 6 15:08:53 2014 +0530
Committer: Sanjay Tripathi <sa...@citrix.com>
Committed: Tue Mar 11 15:44:51 2014 +0530

----------------------------------------------------------------------
 api/src/com/cloud/agent/api/to/GPUDeviceTO.java |  56 +++++
 .../cloud/agent/api/to/VirtualMachineTO.java    |   9 +
 api/src/com/cloud/gpu/GPU.java                  |  49 ++++
 .../org/apache/cloudstack/api/ApiConstants.java |   5 +
 .../offering/CreateServiceOfferingCmd.java      |  18 +-
 .../cloudstack/api/response/GpuResponse.java    |  46 ++++
 .../cloudstack/api/response/HostResponse.java   |   8 +
 .../cloudstack/api/response/UserVmResponse.java |  10 +
 .../cloudstack/api/response/VgpuResponse.java   |  52 +++++
 .../com/cloud/agent/api/GetGPUStatsAnswer.java  |  36 +++
 .../com/cloud/agent/api/GetGPUStatsCommand.java |  47 ++++
 .../cloud/agent/api/StartupRoutingCommand.java  |   9 +
 core/src/com/cloud/agent/api/StopCommand.java   |   9 +
 .../src/com/cloud/resource/ResourceManager.java |  41 ++++
 .../com/cloud/vm/VirtualMachineManagerImpl.java |  18 ++
 .../spring-engine-schema-core-daos-context.xml  |   2 +
 .../src/com/cloud/gpu/HostGpuGroupsVO.java      |  70 ++++++
 .../schema/src/com/cloud/gpu/VGPUTypesVO.java   |  82 +++++++
 .../src/com/cloud/gpu/dao/HostGpuGroupsDao.java |  60 +++++
 .../com/cloud/gpu/dao/HostGpuGroupsDaoImpl.java |  94 ++++++++
 .../src/com/cloud/gpu/dao/VGPUTypesDao.java     |  48 ++++
 .../src/com/cloud/gpu/dao/VGPUTypesDaoImpl.java |  95 ++++++++
 engine/schema/src/com/cloud/host/HostVO.java    |  13 ++
 .../src/com/cloud/host/dao/HostDaoImpl.java     |  18 ++
 .../cloud/service/ServiceOfferingDetailsVO.java |   4 +
 .../xen/resource/CitrixResourceBase.java        | 108 +++++++++
 .../allocator/impl/FirstFitAllocator.java       |  17 +-
 server/src/com/cloud/api/ApiDBUtils.java        |  30 +++
 .../cloud/api/query/dao/HostJoinDaoImpl.java    |  25 ++
 .../cloud/api/query/dao/UserVmJoinDaoImpl.java  |   6 +
 .../configuration/ConfigurationManagerImpl.java |  54 ++++-
 .../deploy/DeploymentPlanningManagerImpl.java   |  14 +-
 .../cloud/hypervisor/HypervisorGuruBase.java    |  15 ++
 .../cloud/network/NetworkUsageManagerImpl.java  |   4 +
 .../com/cloud/resource/ResourceManagerImpl.java |  97 +++++++-
 .../com/cloud/server/ManagementServerImpl.java  |  12 +
 server/src/com/cloud/server/StatsCollector.java |  21 ++
 .../com/cloud/storage/VolumeApiServiceImpl.java |   8 +
 server/src/com/cloud/vm/UserVmManagerImpl.java  |  10 +
 .../cloud/resource/MockResourceManagerImpl.java |  31 +++
 .../vm/DeploymentPlanningManagerImplTest.java   |  12 +
 server/test/resources/createNetworkOffering.xml |   4 +-
 setup/db/db/schema-430to440.sql                 |  18 ++
 .../smoke/test_deploy_vgpu_enabled_vm.py        | 227 +++++++++++++++++++
 tools/marvin/marvin/integration/lib/base.py     |   3 +
 ui/scripts/configuration.js                     |  73 ++++++
 ui/scripts/instances.js                         |   4 +-
 47 files changed, 1671 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/api/src/com/cloud/agent/api/to/GPUDeviceTO.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/agent/api/to/GPUDeviceTO.java b/api/src/com/cloud/agent/api/to/GPUDeviceTO.java
new file mode 100644
index 0000000..8bc9e52
--- /dev/null
+++ b/api/src/com/cloud/agent/api/to/GPUDeviceTO.java
@@ -0,0 +1,56 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.agent.api.to;
+
+import java.util.HashMap;
+
+public class GPUDeviceTO {
+
+    private String gpuGroup;
+    private String vgpuType;
+    private HashMap<String, HashMap<String, Long>> groupDetails = new HashMap<String, HashMap<String, Long>>();
+
+    public GPUDeviceTO( String gpuGroup, String vgpuType, HashMap<String, HashMap<String, Long>> groupDetails) {
+        this.gpuGroup = gpuGroup;
+        this.vgpuType = vgpuType;
+        this.groupDetails = groupDetails;
+    }
+
+    public String getGpuGroup() {
+        return gpuGroup;
+    }
+
+    public String getVgpuType() {
+        return vgpuType;
+    }
+
+    public void setGpuGroup(String gpuGroup) {
+        this.gpuGroup = gpuGroup;
+    }
+
+    public void setVgpuType(String vgpuType) {
+        this.vgpuType = vgpuType;
+    }
+
+    public HashMap<String, HashMap<String, Long>> getGroupDetails() {
+        return groupDetails;
+    }
+
+    public void setGroupDetails(HashMap<String, HashMap<String, Long>> groupDetails) {
+        this.groupDetails = groupDetails;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/api/src/com/cloud/agent/api/to/VirtualMachineTO.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java
index bed3e1d..bbd8385 100644
--- a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java
+++ b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java
@@ -60,6 +60,7 @@ public class VirtualMachineTO {
 
     DiskTO[] disks;
     NicTO[] nics;
+    GPUDeviceTO gpuDevice;
 
     public VirtualMachineTO(long id, String instanceName, VirtualMachine.Type type, int cpus, Integer speed, long minRam, long maxRam, BootloaderType bootloader,
             String os, boolean enableHA, boolean limitCpuUse, String vncPassword) {
@@ -266,4 +267,12 @@ public class VirtualMachineTO {
         this.uuid = uuid;
     }
 
+    public GPUDeviceTO getGpuDevice() {
+        return gpuDevice;
+    }
+
+    public void setGpuDevice(GPUDeviceTO gpuDevice) {
+        this.gpuDevice = gpuDevice;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/api/src/com/cloud/gpu/GPU.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/gpu/GPU.java b/api/src/com/cloud/gpu/GPU.java
new file mode 100644
index 0000000..0eb4667
--- /dev/null
+++ b/api/src/com/cloud/gpu/GPU.java
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.gpu;
+
+
+public class GPU {
+
+    public enum Keys {
+        pciDevice,
+        vgpuType
+    }
+    public enum Type {
+        GPU_Passthrough,
+        VGPU
+    }
+
+    public enum vGPUType {
+        GRID_K100("GRID K100"),
+        GRID_K140Q("GRID K140Q"),
+        GRID_K200("GRID K200"),
+        GRID_K240Q("GRID K240Q"),
+        GRID_K260("GRID K260Q"),
+        passthrough("passthrough");
+
+        private String type;
+
+        vGPUType(String type) {
+            this.type = type;
+        }
+
+        public String getType() {
+            return type;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/api/src/org/apache/cloudstack/api/ApiConstants.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index f0de48e..0a3fafd 100755
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -581,6 +581,11 @@ public class ApiConstants {
     public static final String PASSIVE = "passive";
     public static final String VERSION = "version";
     public static final String START = "start";
+    public static final String GPUGROUP = "gpugroup";
+    public static final String GPUGROUPNAME = "gpugroupname";
+    public static final String VGPU = "vgpu";
+    public static final String VGPUTYPE = "vgputype";
+    public static final String REMAININGCAPACITY = "remainingcapacity";
 
     public enum HostDetails {
         all, capacity, events, stats, min;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java b/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java
index 4143c2e..42bd95d 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java
@@ -17,6 +17,8 @@
 package org.apache.cloudstack.api.command.admin.offering;
 
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
 
 import org.apache.log4j.Logger;
@@ -206,13 +208,17 @@ public class CreateServiceOfferingCmd extends BaseCmd {
     }
 
     public Map<String, String> getDetails() {
-        if (details == null || details.isEmpty()) {
-            return null;
+        Map<String, String> detailsMap = null;
+        if (details != null && !details.isEmpty()) {
+            detailsMap = new HashMap<String, String>();
+            Collection<?> props = details.values();
+            Iterator<?> iter = props.iterator();
+            while (iter.hasNext()) {
+                HashMap<String, String> detail = (HashMap<String, String>) iter.next();
+                detailsMap.putAll(detail);
+            }
         }
-
-        Collection<String> paramsCollection = details.values();
-        Map<String, String> params = (Map<String, String>)(paramsCollection.toArray())[0];
-        return params;
+        return detailsMap;
     }
 
     public Long getBytesReadRate() {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/api/src/org/apache/cloudstack/api/response/GpuResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/GpuResponse.java b/api/src/org/apache/cloudstack/api/response/GpuResponse.java
new file mode 100644
index 0000000..b655749
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/response/GpuResponse.java
@@ -0,0 +1,46 @@
+// 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 org.apache.cloudstack.api.response;
+
+import java.util.List;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+
+public class GpuResponse extends BaseResponse {
+
+    @SerializedName(ApiConstants.GPUGROUPNAME)
+    @Param(description = "GPU cards present in the host")
+    private String gpuGroupName;
+
+    @SerializedName(ApiConstants.VGPU)
+    @Param(description = "the list of enabled vGPUs", responseObject = VgpuResponse.class)
+    private List<VgpuResponse> vgpu;
+
+    public void setGpuGroupName(String gpuGroupName) {
+        this.gpuGroupName = gpuGroupName;
+    }
+
+    public void setVgpu(List<VgpuResponse> vgpu) {
+        this.vgpu = vgpu;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/api/src/org/apache/cloudstack/api/response/HostResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/HostResponse.java b/api/src/org/apache/cloudstack/api/response/HostResponse.java
index e2d8eb5..1fbc668 100644
--- a/api/src/org/apache/cloudstack/api/response/HostResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/HostResponse.java
@@ -17,6 +17,7 @@
 package org.apache.cloudstack.api.response;
 
 import java.util.Date;
+import java.util.List;
 
 import com.google.gson.annotations.SerializedName;
 
@@ -135,6 +136,10 @@ public class HostResponse extends BaseResponse {
     @Param(description = "the amount of the host's memory currently used")
     private Long memoryUsed;
 
+    @SerializedName(ApiConstants.GPUGROUP)
+    @Param(description = "GPU cards present in the host", responseObject = GpuResponse.class)
+    private List<GpuResponse> gpuGroup;
+
     @SerializedName("disksizetotal")
     @Param(description = "the total disk size of the host")
     private Long diskSizeTotal;
@@ -320,6 +325,9 @@ public class HostResponse extends BaseResponse {
         this.memoryUsed = memoryUsed;
     }
 
+    public void setGpuGroups(List<GpuResponse> gpuGroup) {
+        this.gpuGroup = gpuGroup;
+    }
     public void setDiskSizeTotal(Long diskSizeTotal) {
         this.diskSizeTotal = diskSizeTotal;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
index 84d532b..d6ce84f 100644
--- a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
@@ -164,6 +164,10 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
     @Param(description = "the memory allocated for the virtual machine")
     private Integer memory;
 
+    @SerializedName(ApiConstants.VGPU)
+    @Param(description = "the vgpu type used by the virtual machine")
+    private String vgpu;
+
     @SerializedName("cpuused")
     @Param(description = "the amount of the vm's CPU currently used")
     private String cpuUsed;
@@ -420,6 +424,9 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
         return memory;
     }
 
+    public String getVgpu() {
+        return vgpu;
+    }
     public String getCpuUsed() {
         return cpuUsed;
     }
@@ -643,6 +650,9 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
         this.memory = memory;
     }
 
+    public void setVgpu(String vgpu) {
+        this.vgpu = vgpu;
+    }
     public void setCpuUsed(String cpuUsed) {
         this.cpuUsed = cpuUsed;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/api/src/org/apache/cloudstack/api/response/VgpuResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/VgpuResponse.java b/api/src/org/apache/cloudstack/api/response/VgpuResponse.java
new file mode 100644
index 0000000..17e194b
--- /dev/null
+++ b/api/src/org/apache/cloudstack/api/response/VgpuResponse.java
@@ -0,0 +1,52 @@
+// 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 org.apache.cloudstack.api.response;
+
+import com.google.gson.annotations.SerializedName;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+
+public class VgpuResponse extends BaseResponse {
+
+    @SerializedName(ApiConstants.VGPUTYPE)
+    @Param(description = "Model Name of vGPU")
+    private String name;
+
+    @SerializedName(ApiConstants.REMAININGCAPACITY)
+    @Param(description = "No. of more VMs can be deployped with this vGPU type")
+    private Long capacity;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Long getCapacity() {
+        return capacity;
+    }
+
+    public void setCapacity(Long capacity) {
+        this.capacity = capacity;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/core/src/com/cloud/agent/api/GetGPUStatsAnswer.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/GetGPUStatsAnswer.java b/core/src/com/cloud/agent/api/GetGPUStatsAnswer.java
new file mode 100644
index 0000000..566eed5
--- /dev/null
+++ b/core/src/com/cloud/agent/api/GetGPUStatsAnswer.java
@@ -0,0 +1,36 @@
+//Licensed to the Apache Software Foundation (ASF) under one
+//or more contributor license agreements.  See the NOTICE file
+//distributed with this work for additional information
+//regarding copyright ownership.  The ASF licenses this file
+//to you under the Apache License, Version 2.0 (the
+//"License"); you may not use this file except in compliance
+//with the License.  You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing,
+//software distributed under the License is distributed on an
+//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+//KIND, either express or implied.  See the License for the
+//specific language governing permissions and limitations
+//under the License.
+package com.cloud.agent.api;
+
+import java.util.HashMap;
+
+import com.cloud.agent.api.LogLevel.Log4jLevel;
+
+@LogLevel(Log4jLevel.Trace)
+public class GetGPUStatsAnswer extends Answer {
+
+    private HashMap<String, HashMap<String, Long>> groupDetails;
+
+    public GetGPUStatsAnswer(GetGPUStatsCommand cmd, HashMap<String, HashMap<String, Long>> groupDetails) {
+        super(cmd);
+        this.groupDetails = groupDetails;
+    }
+
+    public HashMap<String, HashMap<String, Long>> getGroupDetails() {
+        return this.groupDetails;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/core/src/com/cloud/agent/api/GetGPUStatsCommand.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/GetGPUStatsCommand.java b/core/src/com/cloud/agent/api/GetGPUStatsCommand.java
new file mode 100644
index 0000000..047f562
--- /dev/null
+++ b/core/src/com/cloud/agent/api/GetGPUStatsCommand.java
@@ -0,0 +1,47 @@
+//Licensed to the Apache Software Foundation (ASF) under one
+//or more contributor license agreements.  See the NOTICE file
+//distributed with this work for additional information
+//regarding copyright ownership.  The ASF licenses this file
+//to you under the Apache License, Version 2.0 (the
+//"License"); you may not use this file except in compliance
+//with the License.  You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing,
+//software distributed under the License is distributed on an
+//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+//KIND, either express or implied.  See the License for the
+//specific language governing permissions and limitations
+//under the License.
+package com.cloud.agent.api;
+
+import com.cloud.agent.api.LogLevel.Log4jLevel;
+
+@LogLevel(Log4jLevel.Trace)
+public class GetGPUStatsCommand extends Command
+{
+    String hostGuid;
+    String hostName;
+
+    protected GetGPUStatsCommand() {
+    }
+
+    public GetGPUStatsCommand(String hostGuid, String hostName) {
+        this.hostGuid = hostGuid;
+        this.hostName = hostName;
+    }
+
+    public String getHostGuid(){
+        return this.hostGuid;
+    }
+
+    public String getHostName(){
+        return this.hostName;
+    }
+
+    @Override
+    public boolean executeInSequence() {
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/core/src/com/cloud/agent/api/StartupRoutingCommand.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/StartupRoutingCommand.java b/core/src/com/cloud/agent/api/StartupRoutingCommand.java
index 8c0eb8a..dc37113 100755
--- a/core/src/com/cloud/agent/api/StartupRoutingCommand.java
+++ b/core/src/com/cloud/agent/api/StartupRoutingCommand.java
@@ -70,6 +70,7 @@ public class StartupRoutingCommand extends StartupCommand {
     HypervisorType hypervisorType;
     Map<String, String> hostDetails; //stuff like host os, cpu capabilities
     String hypervisorVersion;
+    HashMap<String, HashMap<String, Long>> groupDetails = new HashMap<String, HashMap<String, Long>>();
 
     public StartupRoutingCommand() {
         super(Host.Type.Routing);
@@ -244,4 +245,12 @@ public class StartupRoutingCommand extends StartupCommand {
     public void setHostVmStateReport(Map<String, HostVmStateReportEntry> hostVmStateReport) {
         this._hostVmStateReport = hostVmStateReport;
     }
+
+    public  HashMap<String, HashMap<String, Long>> getGpuGroupDetails() {
+        return groupDetails;
+    }
+
+    public void setGpuGroupDetails(HashMap<String, HashMap<String, Long>> groupDetails) {
+        this.groupDetails = groupDetails;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/core/src/com/cloud/agent/api/StopCommand.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/agent/api/StopCommand.java b/core/src/com/cloud/agent/api/StopCommand.java
index 6a29aa6..00d7f5f 100755
--- a/core/src/com/cloud/agent/api/StopCommand.java
+++ b/core/src/com/cloud/agent/api/StopCommand.java
@@ -16,6 +16,7 @@
 // under the License.
 package com.cloud.agent.api;
 
+import com.cloud.agent.api.to.GPUDeviceTO;
 import com.cloud.vm.VirtualMachine;
 
 public class StopCommand extends RebootCommand {
@@ -23,6 +24,7 @@ public class StopCommand extends RebootCommand {
     private String urlPort = null;
     private String publicConsoleProxyIpAddress = null;
     boolean executeInSequence = false;
+    private GPUDeviceTO gpuDevice;
 
     protected StopCommand() {
     }
@@ -62,4 +64,11 @@ public class StopCommand extends RebootCommand {
         return this.publicConsoleProxyIpAddress;
     }
 
+    public GPUDeviceTO getGpuDevice() {
+        return this.gpuDevice;
+    }
+
+    public void setGpuDevice(GPUDeviceTO gpuDevice) {
+        this.gpuDevice = gpuDevice;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/engine/components-api/src/com/cloud/resource/ResourceManager.java
----------------------------------------------------------------------
diff --git a/engine/components-api/src/com/cloud/resource/ResourceManager.java b/engine/components-api/src/com/cloud/resource/ResourceManager.java
index 95fb385..5a9bddb 100755
--- a/engine/components-api/src/com/cloud/resource/ResourceManager.java
+++ b/engine/components-api/src/com/cloud/resource/ResourceManager.java
@@ -17,15 +17,18 @@
 // under the License.
 package com.cloud.resource;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import com.cloud.agent.api.StartupCommand;
 import com.cloud.agent.api.StartupRoutingCommand;
+import com.cloud.agent.api.to.GPUDeviceTO;
 import com.cloud.dc.DataCenterVO;
 import com.cloud.dc.HostPodVO;
 import com.cloud.dc.PodCluster;
 import com.cloud.exception.AgentUnavailableException;
+import com.cloud.gpu.HostGpuGroupsVO;
 import com.cloud.host.Host;
 import com.cloud.host.Host.Type;
 import com.cloud.host.HostStats;
@@ -137,4 +140,42 @@ public interface ResourceManager extends ResourceService {
      * @return
      */
     List<HostVO> listAllUpAndEnabledNonHAHosts(Type type, Long clusterId, Long podId, long dcId);
+
+    /**
+     * Check if host has GPU devices available
+     * @param hostId the host to be checked
+     * @param vgpuType the VGPU type
+     * @return true when the host has the capacity with given VGPU type
+     */
+    boolean isGPUDeviceAvailable(long hostId, String vgpuType);
+
+    /**
+     * Get available GPU device
+     * @param hostId the host to be checked
+     * @param vgpuType the VGPU type
+     * @return GPUDeviceTO[]
+     */
+    GPUDeviceTO getGPUDevice(long hostId, String vgpuType);
+
+    /**
+     * Return listof available GPU devices
+     * @param hostId, the host to be checked
+     * @param vgpuType the VGPU type
+     * @return List of HostGpuGroupsVO.
+     */
+    List<HostGpuGroupsVO> listAvailableGPUDevice(long hostId, String vgpuType);
+
+    /**
+     * Update GPU device details (post VM deployment)
+     * @param hostId, the dest host Id
+     * @param groupDetails, capacity of GPU group.
+     */
+    void updateGPUDetails(long hostId, HashMap<String, HashMap<String, Long>> groupDetails);
+
+    /**
+     * Get GPU details for a host
+     * @param host, the Host object
+     * @return Details of groupNames and enabled VGPU type with remaining capacity.
+     */
+    HashMap<String, HashMap<String, Long>> getGPUStatistics(HostVO host);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
----------------------------------------------------------------------
diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 8edbb76..609aefa 100755
--- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -103,6 +103,7 @@ import com.cloud.agent.api.StopCommand;
 import com.cloud.agent.api.UnPlugNicAnswer;
 import com.cloud.agent.api.UnPlugNicCommand;
 import com.cloud.agent.api.to.DiskTO;
+import com.cloud.agent.api.to.GPUDeviceTO;
 import com.cloud.agent.api.to.NicTO;
 import com.cloud.agent.api.to.VirtualMachineTO;
 import com.cloud.agent.manager.Commands;
@@ -139,6 +140,7 @@ import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.exception.OperationTimedoutException;
 import com.cloud.exception.ResourceUnavailableException;
 import com.cloud.exception.StorageUnavailableException;
+import com.cloud.gpu.dao.VGPUTypesDao;
 import com.cloud.ha.HighAvailabilityManager;
 import com.cloud.ha.HighAvailabilityManager.WorkType;
 import com.cloud.host.Host;
@@ -276,6 +278,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
     @Inject
     protected AffinityGroupVMMapDao _affinityGroupVMMapDao;
     @Inject
+    protected VGPUTypesDao _vgpuTypesDao;
+    @Inject
     protected EntityManager _entityMgr;
 
     @Inject
@@ -1026,6 +1030,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                                 throw new ConcurrentOperationException("Unable to transition to a new state.");
                             }
 
+                            // Update GPU device capacity
+                            GPUDeviceTO gpuDevice = startAnswer.getVirtualMachine().getGpuDevice();
+                            if (gpuDevice != null) {
+                                _resourceMgr.updateGPUDetails(destHostId, gpuDevice.getGroupDetails());
+                            }
+
                             startedVm = vm;
                             if (s_logger.isDebugEnabled()) {
                                 s_logger.debug("Start completed for VM " + vm);
@@ -1221,6 +1231,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     }
                 }
 
+                GPUDeviceTO gpuDevice = stop.getGpuDevice();
+                if (gpuDevice != null) {
+                    _resourceMgr.updateGPUDetails(vm.getHostId(), gpuDevice.getGroupDetails());
+                }
                 if (!answer.getResult()) {
                     s_logger.debug("Unable to stop VM due to " + answer.getDetails());
                     return false;
@@ -1483,6 +1497,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
                     throw new CloudRuntimeException("Unable to stop the virtual machine due to " + answer.getDetails());
                 }
                 vmGuru.finalizeStop(profile, answer);
+                GPUDeviceTO gpuDevice = stop.getGpuDevice();
+                if (gpuDevice != null) {
+                    _resourceMgr.updateGPUDetails(vm.getHostId(), gpuDevice.getGroupDetails());
+                }
             } else {
                 throw new CloudRuntimeException("Invalid answer received in response to a StopCommand on " + vm.instanceName);
             }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
----------------------------------------------------------------------
diff --git a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
index 08efb83..765d86c 100644
--- a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
+++ b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml
@@ -316,6 +316,8 @@
   <bean id="networkOfferingDetailsDaoImpl" class="com.cloud.offerings.dao.NetworkOfferingDetailsDaoImpl" />
   <bean id="serviceOfferingDetailsDaoImpl" class="com.cloud.service.dao.ServiceOfferingDetailsDaoImpl"/>
   <bean id="networkDetailsDaoImpl" class="com.cloud.network.dao.NetworkDetailsDaoImpl" />
+  <bean id="hostGpuGroupsDaoImpl" class="com.cloud.gpu.dao.HostGpuGroupsDaoImpl" />
+  <bean id="vGPUTypesDaoImpl" class="com.cloud.gpu.dao.VGPUTypesDaoImpl" />
   <bean id="AffinityGroupDaoImpl" class="org.apache.cloudstack.affinity.dao.AffinityGroupDaoImpl" />
   <bean id="AffinityGroupVMMapDaoImpl" class="org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDaoImpl" />
   <bean id="AffinityGroupDomainMapDaoImpl" class="org.apache.cloudstack.affinity.dao.AffinityGroupDomainMapDaoImpl" />

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/engine/schema/src/com/cloud/gpu/HostGpuGroupsVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/gpu/HostGpuGroupsVO.java b/engine/schema/src/com/cloud/gpu/HostGpuGroupsVO.java
new file mode 100644
index 0000000..1c186a1
--- /dev/null
+++ b/engine/schema/src/com/cloud/gpu/HostGpuGroupsVO.java
@@ -0,0 +1,70 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.gpu;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+@Entity
+@Table(name="host_gpu_groups")
+public class HostGpuGroupsVO implements InternalIdentity {
+    @Id
+    @GeneratedValue(strategy=GenerationType.IDENTITY)
+    @Column(name="id")
+    private long id;
+
+    @Column(name="group_name")
+    private String groupName;
+
+    @Column(name="host_id")
+    private long hostId;
+
+    protected HostGpuGroupsVO() {
+    }
+
+    public HostGpuGroupsVO(long hostId, String groupName) {
+        this.hostId = hostId;
+        this.groupName = groupName;
+    }
+
+    public long getHostId() {
+        return hostId;
+    }
+
+    public void setHostId(long hostId) {
+        this.hostId = hostId;
+    }
+
+    public String getGroupName() {
+        return groupName;
+    }
+
+    public void setGroupName(String groupName) {
+        this.groupName = groupName;
+    }
+
+    @Override
+    public long getId() {
+        return id;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/engine/schema/src/com/cloud/gpu/VGPUTypesVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/gpu/VGPUTypesVO.java b/engine/schema/src/com/cloud/gpu/VGPUTypesVO.java
new file mode 100644
index 0000000..586a0c9
--- /dev/null
+++ b/engine/schema/src/com/cloud/gpu/VGPUTypesVO.java
@@ -0,0 +1,82 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.gpu;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.cloudstack.api.InternalIdentity;
+
+@Entity
+@Table(name="vgpu_types")
+public class VGPUTypesVO implements InternalIdentity {
+    @Id
+    @GeneratedValue(strategy=GenerationType.IDENTITY)
+    @Column(name="id")
+    private long id;
+
+    @Column(name="vgpu_type")
+    private String vgpuType;
+
+    @Column(name="gpu_group_id")
+    private long gpuGroupId;
+
+    @Column(name="remaining_vm_capacity")
+    private long remainingCapacity;
+
+    protected VGPUTypesVO() {
+    }
+
+    public VGPUTypesVO(String vgpuType, long gpuGroupId, long remainingCapacity) {
+        this.vgpuType = vgpuType;
+        this.gpuGroupId = gpuGroupId;
+        this.remainingCapacity = remainingCapacity;
+    }
+
+    public String getVgpuType() {
+        return vgpuType;
+    }
+
+    public void setVgpuType(String vgpuType) {
+        this.vgpuType = vgpuType;
+    }
+
+    public long getGpuGroupId() {
+        return gpuGroupId;
+    }
+
+    public void setGpuGroupId(long gpuGroupId) {
+        this.gpuGroupId = gpuGroupId;
+    }
+
+    public long getRemainingCapacity() {
+        return remainingCapacity;
+    }
+
+    public void setRemainingCapacity(long remainingCapacity) {
+        this.remainingCapacity = remainingCapacity;
+    }
+
+    @Override
+    public long getId() {
+        return id;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/engine/schema/src/com/cloud/gpu/dao/HostGpuGroupsDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/gpu/dao/HostGpuGroupsDao.java b/engine/schema/src/com/cloud/gpu/dao/HostGpuGroupsDao.java
new file mode 100644
index 0000000..5864144
--- /dev/null
+++ b/engine/schema/src/com/cloud/gpu/dao/HostGpuGroupsDao.java
@@ -0,0 +1,60 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.gpu.dao;
+
+import java.util.List;
+
+import com.cloud.gpu.HostGpuGroupsVO;
+import com.cloud.utils.db.GenericDao;
+
+public interface HostGpuGroupsDao extends GenericDao<HostGpuGroupsVO, Long> {
+
+    /**
+     * Find host device by hostId and PCI ID
+     * @param hostId the host
+     * @param groupName GPU group
+     * @return HostGpuGroupsVO
+     */
+    HostGpuGroupsVO findByHostIdGroupName(long hostId, String groupName);
+
+    /**
+     * List all the host Ids, that are GPU enabled.
+     * @return list of hostIds
+     */
+    List<Long> listHostIds();
+
+    /**
+     * Return a list by hostId.
+     * @param hostId the host
+     * @return HostGpuGroupsVO
+     */
+    List<HostGpuGroupsVO> listByHostId(long hostId);
+
+    /**
+     * Delete entries by hostId.
+     * @param hostId the host
+     */
+    void deleteGpuEntries(long hostId);
+
+    /**
+     * Save the list of GPU groups belonging to a host
+     * @param hostId the host
+     * @param gpuGroups the list of GPU groups to save
+     */
+    void persist(long hostId, List<String> gpuGroups);
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/engine/schema/src/com/cloud/gpu/dao/HostGpuGroupsDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/gpu/dao/HostGpuGroupsDaoImpl.java b/engine/schema/src/com/cloud/gpu/dao/HostGpuGroupsDaoImpl.java
new file mode 100644
index 0000000..6bddea2
--- /dev/null
+++ b/engine/schema/src/com/cloud/gpu/dao/HostGpuGroupsDaoImpl.java
@@ -0,0 +1,94 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.gpu.dao;
+
+import java.util.List;
+
+import javax.ejb.Local;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import com.cloud.gpu.HostGpuGroupsVO;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.GenericSearchBuilder;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+@Component
+@Local(value = HostGpuGroupsDao.class)
+public class HostGpuGroupsDaoImpl extends GenericDaoBase<HostGpuGroupsVO, Long> implements HostGpuGroupsDao {
+    private static final Logger s_logger = Logger.getLogger(HostGpuGroupsDaoImpl.class);
+
+    private final SearchBuilder<HostGpuGroupsVO> _hostIdGroupNameSearch;
+    private final SearchBuilder<HostGpuGroupsVO> _searchByHostId;
+    private final GenericSearchBuilder<HostGpuGroupsVO, Long> _searchHostIds;
+
+    public HostGpuGroupsDaoImpl() {
+
+        _hostIdGroupNameSearch = createSearchBuilder();
+        _hostIdGroupNameSearch.and("hostId", _hostIdGroupNameSearch.entity().getHostId(), SearchCriteria.Op.EQ);
+        _hostIdGroupNameSearch.and("groupName", _hostIdGroupNameSearch.entity().getGroupName(), SearchCriteria.Op.EQ);
+        _hostIdGroupNameSearch.done();
+
+        _searchByHostId = createSearchBuilder();
+        _searchByHostId.and("hostId", _searchByHostId.entity().getHostId(), SearchCriteria.Op.EQ);
+        _searchByHostId.done();
+
+        _searchHostIds = createSearchBuilder(Long.class);
+        _searchHostIds.selectFields(_searchHostIds.entity().getHostId());
+        _searchHostIds.done();
+    }
+
+    @Override
+    public HostGpuGroupsVO findByHostIdGroupName(long hostId, String groupName) {
+        SearchCriteria<HostGpuGroupsVO> sc = _hostIdGroupNameSearch.create();
+        sc.setParameters("hostId", hostId);
+        sc.setParameters("groupName", groupName);
+        return findOneBy(sc);
+    }
+
+    @Override
+    public List<Long> listHostIds() {
+        SearchCriteria<Long> sc = _searchHostIds.create();
+        return customSearch(sc, null);
+    }
+
+    @Override
+    public List<HostGpuGroupsVO> listByHostId(long hostId) {
+        SearchCriteria<HostGpuGroupsVO> sc = _searchByHostId.create();
+        sc.setParameters("hostId", hostId);
+        return listBy(sc);
+    }
+
+    @Override
+    public void persist(long hostId, List<String> gpuGroups) {
+        for (String groupName : gpuGroups) {
+            if (findByHostIdGroupName(hostId, groupName) == null) {
+                HostGpuGroupsVO record = new HostGpuGroupsVO(hostId, groupName);
+                persist(record);
+            }
+        }
+    }
+
+    @Override
+    public void deleteGpuEntries(long hostId) {
+        SearchCriteria<HostGpuGroupsVO> sc = _searchByHostId.create();
+        sc.setParameters("hostId", hostId);
+        remove(sc);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDao.java b/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDao.java
new file mode 100644
index 0000000..2872cfd
--- /dev/null
+++ b/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDao.java
@@ -0,0 +1,48 @@
+//Licensed to the Apache Software Foundation (ASF) under one
+//or more contributor license agreements.  See the NOTICE file
+//distributed with this work for additional information
+//regarding copyright ownership.  The ASF licenses this file
+//to you under the Apache License, Version 2.0 (the
+//"License"); you may not use this file except in compliance
+//with the License.  You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing,
+//software distributed under the License is distributed on an
+//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+//KIND, either express or implied.  See the License for the
+//specific language governing permissions and limitations
+//under the License.
+package com.cloud.gpu.dao;
+
+import java.util.HashMap;
+import java.util.List;
+
+import com.cloud.gpu.VGPUTypesVO;
+import com.cloud.utils.db.GenericDao;
+
+public interface VGPUTypesDao extends GenericDao<VGPUTypesVO, Long> {
+
+ /**
+  * Find VGPU types by group Id
+  * @param groupId of the GPU group
+  * @return list of VGPUTypesVO
+  */
+ List<VGPUTypesVO> listByGroupId(long groupId);
+
+ /**
+  * Find VGPU type by group Id and VGPU type
+  * @param groupId of the GPU group
+  * @param vgpuType name of VGPU type
+  * @return VGPUTypesVO
+  */
+ VGPUTypesVO findByGroupIdVGPUType(long groupId, String vgpuType);
+
+ /**
+  * Save the list of enabled VGPU types
+  * @param hostId the host
+  * @param groupDetails with enabled VGPU types
+  */
+ void persist(long hostId, HashMap<String, HashMap<String, Long>> groupDetails);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDaoImpl.java b/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDaoImpl.java
new file mode 100644
index 0000000..7cc83cc
--- /dev/null
+++ b/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDaoImpl.java
@@ -0,0 +1,95 @@
+//Licensed to the Apache Software Foundation (ASF) under one
+//or more contributor license agreements.  See the NOTICE file
+//distributed with this work for additional information
+//regarding copyright ownership.  The ASF licenses this file
+//to you under the Apache License, Version 2.0 (the
+//"License"); you may not use this file except in compliance
+//with the License.  You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing,
+//software distributed under the License is distributed on an
+//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+//KIND, either express or implied.  See the License for the
+//specific language governing permissions and limitations
+//under the License.
+package com.cloud.gpu.dao;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import com.cloud.gpu.HostGpuGroupsVO;
+import com.cloud.gpu.VGPUTypesVO;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+
+@Component
+@Local(value = VGPUTypesDao.class)
+public class VGPUTypesDaoImpl extends GenericDaoBase<VGPUTypesVO, Long> implements VGPUTypesDao {
+    private static final Logger s_logger = Logger.getLogger(VGPUTypesDaoImpl.class);
+
+    private final SearchBuilder<VGPUTypesVO> _searchByGroupId;
+    private final SearchBuilder<VGPUTypesVO> _searchByGroupIdVGPUType;
+    // private final SearchBuilder<VGPUTypesVO> _searchByHostId;
+    // private final SearchBuilder<VGPUTypesVO> _searchForStaleEntries;
+
+    @Inject protected HostGpuGroupsDao _hostGpuGroupsDao;
+
+    public VGPUTypesDaoImpl() {
+
+        _searchByGroupId = createSearchBuilder();
+        _searchByGroupId.and("groupId", _searchByGroupId.entity().getGpuGroupId(), SearchCriteria.Op.EQ);
+        _searchByGroupId.done();
+
+        _searchByGroupIdVGPUType = createSearchBuilder();
+        _searchByGroupIdVGPUType.and("groupId", _searchByGroupIdVGPUType.entity().getGpuGroupId(), SearchCriteria.Op.EQ);
+        _searchByGroupIdVGPUType.and("vgpuType", _searchByGroupIdVGPUType.entity().getVgpuType(), SearchCriteria.Op.EQ);
+        _searchByGroupIdVGPUType.done();
+    }
+
+    @Override
+    public List<VGPUTypesVO> listByGroupId(long groupId) {
+        SearchCriteria<VGPUTypesVO> sc = _searchByGroupId.create();
+        sc.setParameters("groupId", groupId);
+        return listBy(sc);
+    }
+
+    @Override
+    public VGPUTypesVO findByGroupIdVGPUType(long groupId, String vgpuType) {
+        SearchCriteria<VGPUTypesVO> sc = _searchByGroupIdVGPUType.create();
+        sc.setParameters("groupId", groupId);
+        sc.setParameters("vgpuType", vgpuType);
+        return findOneBy(sc);
+    }
+
+    @Override
+    public void persist(long hostId, HashMap<String, HashMap<String, Long>> groupDetails) {
+        Iterator<Entry<String, HashMap<String, Long>>> it1 = groupDetails.entrySet().iterator();
+        while (it1.hasNext()) {
+            Entry<String, HashMap<String, Long>> entry = it1.next();
+            HostGpuGroupsVO gpuGroup = _hostGpuGroupsDao.findByHostIdGroupName(hostId, entry.getKey());
+            HashMap<String, Long> values = entry.getValue();
+            Iterator<Entry<String, Long>> it2 = values.entrySet().iterator();
+            while (it2.hasNext()) {
+                Entry<String, Long> record = it2.next();
+                VGPUTypesVO vgpuType = null;
+                if ((vgpuType = findByGroupIdVGPUType(gpuGroup.getId(), record.getKey())) == null) {
+                    persist(new VGPUTypesVO(record.getKey(), gpuGroup.getId(), record.getValue()));
+                } else {
+                    vgpuType.setRemainingCapacity(record.getValue());
+                    update(vgpuType.getId(), vgpuType);
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/engine/schema/src/com/cloud/host/HostVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/host/HostVO.java b/engine/schema/src/com/cloud/host/HostVO.java
index 56c066b..25cc954 100755
--- a/engine/schema/src/com/cloud/host/HostVO.java
+++ b/engine/schema/src/com/cloud/host/HostVO.java
@@ -17,6 +17,7 @@
 package com.cloud.host;
 
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
@@ -153,6 +154,10 @@ public class HostVO implements Host {
     @Transient
     List<String> hostTags;
 
+    // This value is only for saving and current cannot be loaded.
+    @Transient
+    HashMap<String, HashMap<String, Long>> groupDetails = new HashMap<String, HashMap<String, Long>>();
+
     @Override
     public String getStorageIpAddressDeux() {
         return storageIpAddressDeux;
@@ -313,6 +318,14 @@ public class HostVO implements Host {
         this.hostTags = hostTags;
     }
 
+    public  HashMap<String, HashMap<String, Long>> getGpuGroupDetails() {
+        return groupDetails;
+    }
+
+    public void setGpuGroups(HashMap<String, HashMap<String, Long>> groupDetails) {
+        this.groupDetails = groupDetails;
+    }
+
     @Column(name = "data_center_id", nullable = false)
     private long dataCenterId;
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java
index 08a4366..c2a9826 100755
--- a/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java
+++ b/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java
@@ -38,6 +38,8 @@ import com.cloud.cluster.agentlb.HostTransferMapVO;
 import com.cloud.cluster.agentlb.dao.HostTransferMapDao;
 import com.cloud.dc.ClusterVO;
 import com.cloud.dc.dao.ClusterDao;
+import com.cloud.gpu.dao.HostGpuGroupsDao;
+import com.cloud.gpu.dao.VGPUTypesDao;
 import com.cloud.host.Host;
 import com.cloud.host.Host.Type;
 import com.cloud.host.HostTagVO;
@@ -126,6 +128,10 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
     @Inject
     protected HostDetailsDao _detailsDao;
     @Inject
+    protected HostGpuGroupsDao _hostGpuGroupsDao;
+    @Inject
+    protected VGPUTypesDao _vgpuTypesDao;
+    @Inject
     protected HostTagsDao _hostTagsDao;
     @Inject
     protected HostTransferMapDao _hostTransferDao;
@@ -775,6 +781,16 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
         _hostTagsDao.persist(host.getId(), hostTags);
     }
 
+    protected void saveGpuRecords(HostVO host) {
+        HashMap<String, HashMap<String, Long>> groupDetails = host.getGpuGroupDetails();
+        if (groupDetails != null) {
+            // Create/Update GPU group entries
+            _hostGpuGroupsDao.persist(host.getId(), new ArrayList<String>(groupDetails.keySet()));
+            // Create/Update VGPU types entries
+            _vgpuTypesDao.persist(host.getId(), groupDetails);
+        }
+    }
+
     @Override
     @DB
     public HostVO persist(HostVO host) {
@@ -797,6 +813,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
         loadDetails(dbHost);
         saveHostTags(host);
         loadHostTags(dbHost);
+        saveGpuRecords(host);
 
         txn.commit();
 
@@ -816,6 +833,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
 
         saveDetails(host);
         saveHostTags(host);
+        saveGpuRecords(host);
 
         txn.commit();
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/engine/schema/src/com/cloud/service/ServiceOfferingDetailsVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/service/ServiceOfferingDetailsVO.java b/engine/schema/src/com/cloud/service/ServiceOfferingDetailsVO.java
index ed8090b..8dfe527 100644
--- a/engine/schema/src/com/cloud/service/ServiceOfferingDetailsVO.java
+++ b/engine/schema/src/com/cloud/service/ServiceOfferingDetailsVO.java
@@ -60,6 +60,10 @@ public class ServiceOfferingDetailsVO implements ResourceDetail {
         return resourceId;
     }
 
+    public void setResourceId(long serviceOfferingId) {
+        this.resourceId = serviceOfferingId;
+    }
+
     @Override
     public String getName() {
         return name;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
index b1ad63a..d80bddc 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
@@ -56,11 +56,13 @@ import com.trilead.ssh2.SCPClient;
 import com.xensource.xenapi.Bond;
 import com.xensource.xenapi.Connection;
 import com.xensource.xenapi.Console;
+import com.xensource.xenapi.GPUGroup;
 import com.xensource.xenapi.Host;
 import com.xensource.xenapi.HostCpu;
 import com.xensource.xenapi.HostMetrics;
 import com.xensource.xenapi.Network;
 import com.xensource.xenapi.PBD;
+import com.xensource.xenapi.PGPU;
 import com.xensource.xenapi.PIF;
 import com.xensource.xenapi.Pool;
 import com.xensource.xenapi.SR;
@@ -73,6 +75,8 @@ import com.xensource.xenapi.Types.XenAPIException;
 import com.xensource.xenapi.VBD;
 import com.xensource.xenapi.VBDMetrics;
 import com.xensource.xenapi.VDI;
+import com.xensource.xenapi.VGPU;
+import com.xensource.xenapi.VGPUType;
 import com.xensource.xenapi.VIF;
 import com.xensource.xenapi.VLAN;
 import com.xensource.xenapi.VM;
@@ -108,6 +112,8 @@ import com.cloud.agent.api.CreateVMSnapshotCommand;
 import com.cloud.agent.api.DeleteStoragePoolCommand;
 import com.cloud.agent.api.DeleteVMSnapshotAnswer;
 import com.cloud.agent.api.DeleteVMSnapshotCommand;
+import com.cloud.agent.api.GetGPUStatsAnswer;
+import com.cloud.agent.api.GetGPUStatsCommand;
 import com.cloud.agent.api.GetHostStatsAnswer;
 import com.cloud.agent.api.GetHostStatsCommand;
 import com.cloud.agent.api.GetStorageStatsAnswer;
@@ -201,6 +207,7 @@ import com.cloud.agent.api.storage.ResizeVolumeCommand;
 import com.cloud.agent.api.to.DataStoreTO;
 import com.cloud.agent.api.to.DataTO;
 import com.cloud.agent.api.to.DiskTO;
+import com.cloud.agent.api.to.GPUDeviceTO;
 import com.cloud.agent.api.to.IpAddressTO;
 import com.cloud.agent.api.to.NfsTO;
 import com.cloud.agent.api.to.NicTO;
@@ -433,6 +440,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
             return execute((GetHostStatsCommand)cmd);
         } else if (clazz == GetVmStatsCommand.class) {
             return execute((GetVmStatsCommand)cmd);
+        } else if (clazz == GetGPUStatsCommand.class) {
+            return execute((GetGPUStatsCommand) cmd);
         } else if (clazz == GetVmDiskStatsCommand.class) {
             return execute((GetVmDiskStatsCommand)cmd);
         } else if (clazz == CheckHealthCommand.class) {
@@ -1288,6 +1297,65 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         return dynamicMinRam;
     }
 
+    private HashMap<String, HashMap<String, Long>> getGPUGroupDetails(Connection conn) throws XenAPIException, XmlRpcException {
+        HashMap<String, HashMap<String, Long>> groupDetails = new HashMap<String, HashMap<String, Long>>();
+        Host host = Host.getByUuid(conn, _host.uuid);
+        Set<PGPU> pgpus = host.getPGPUs(conn);
+        Iterator<PGPU> iter = pgpus.iterator();
+        while (iter.hasNext()) {
+            PGPU pgpu = iter.next();
+            GPUGroup gpuGroup = pgpu.getGPUGroup(conn);
+            Set<VGPUType> enabledVGPUTypes = gpuGroup.getEnabledVGPUTypes(conn);
+            String groupName = gpuGroup.getNameLabel(conn);
+            HashMap<String, Long> gpuCapacity = new HashMap<String, Long>();
+            if (groupDetails.get(groupName) != null) {
+                gpuCapacity = groupDetails.get(groupName);
+            }
+            // Get remaining capacity of all the enabled VGPU in a PGPU
+            if(enabledVGPUTypes != null) {
+                Iterator<VGPUType> it = enabledVGPUTypes.iterator();
+                while (it.hasNext()) {
+                    VGPUType type = it.next();
+                    String modelName = type.getModelName(conn);
+                    Long remainingCapacity = pgpu.getRemainingCapacity(conn, type);
+                    if (gpuCapacity.get(modelName) != null) {
+                        long newRemainingCapacity = gpuCapacity.get(modelName) + remainingCapacity;
+                        gpuCapacity.put(modelName, newRemainingCapacity);
+                    } else {
+                        gpuCapacity.put(modelName, remainingCapacity);
+                    }
+                }
+            }
+            groupDetails.put(groupName, gpuCapacity);
+        }
+        return groupDetails;
+    }
+
+    protected void createVGPU(Connection conn, StartCommand cmd, VM vm, GPUDeviceTO gpuDevice) throws XenAPIException, XmlRpcException {
+        Set<GPUGroup> groups = GPUGroup.getByNameLabel(conn, gpuDevice.getGpuGroup());
+        assert groups.size() == 1 : "Should only have 1 group but found " + groups.size();
+        GPUGroup gpuGroup = groups.iterator().next();
+
+        Set<VGPUType> vgpuTypes = gpuGroup.getEnabledVGPUTypes(conn);
+        Iterator<VGPUType> iter = vgpuTypes.iterator();
+        VGPUType vgpuType = null;
+        while (iter.hasNext()) {
+            VGPUType entry = iter.next();
+            if (entry.getModelName(conn).equals(gpuDevice.getVgpuType())) {
+                vgpuType = entry;
+            }
+        }
+        String device = "0"; // Only allow device = "0" for now, as XenServer supports just a single vGPU per VM.
+        Map<String, String> other_config = new HashMap<String, String>();
+        VGPU.create(conn, vm, gpuGroup, device, other_config, vgpuType);
+
+        if (s_logger.isDebugEnabled()) {
+            s_logger.debug("Created VGPU of VGPU type [ " + gpuDevice.getVgpuType() + " ] for VM " + cmd.getVirtualMachine().getName());
+        }
+        // Calculate and set remaining GPU capacity in the host.
+        cmd.getVirtualMachine().getGpuDevice().setGroupDetails(getGPUGroupDetails(conn));
+    }
+
     protected VM createVmFromTemplate(Connection conn, VirtualMachineTO vmSpec, Host host) throws XenAPIException, XmlRpcException {
         String guestOsTypeName = getGuestOsType(vmSpec.getOs(), vmSpec.getBootloader() == BootloaderType.CD);
         Set<VM> templates = VM.getByNameLabel(conn, guestOsTypeName);
@@ -1721,6 +1789,13 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
             Host host = Host.getByUuid(conn, _host.uuid);
             vm = createVmFromTemplate(conn, vmSpec, host);
 
+            GPUDeviceTO gpuDevice = vmSpec.getGpuDevice();
+            if (gpuDevice != null) {
+                s_logger.debug("Creating VGPU for of VGPU type: " + gpuDevice.getVgpuType() + " in GPU group "
+                        + gpuDevice.getGpuGroup() + " for VM " + vmName );
+                createVGPU(conn, cmd, vm, gpuDevice);
+            }
+
             for (DiskTO disk : vmSpec.getDisks()) {
                 VDI newVdi = prepareManagedDisk(conn, disk, vmName);
 
@@ -2245,6 +2320,18 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         return hostStats;
     }
 
+    protected GetGPUStatsAnswer execute(GetGPUStatsCommand cmd) {
+        Connection conn = getConnection();
+        HashMap<String, HashMap<String, Long>> groupDetails = new HashMap<String, HashMap<String, Long>>();
+        try {
+            groupDetails = getGPUGroupDetails(conn);
+        } catch (Exception e) {
+            String msg = "Unable to get GPU stats" + e.toString();
+            s_logger.warn(msg, e);
+        }
+        return new GetGPUStatsAnswer(cmd, groupDetails);
+    }
+
     protected GetVmStatsAnswer execute(GetVmStatsCommand cmd) {
         Connection conn = getConnection();
         List<String> vmNames = cmd.getVmNames();
@@ -3566,6 +3653,18 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
 
                     try {
                         if (vm.getPowerState(conn) == VmPowerState.HALTED) {
+                            Set<VGPU> vGPUs = null;
+                            // Get updated GPU details
+                            try {
+                                vGPUs = vm.getVGPUs(conn);
+                            } catch (XenAPIException e2) {
+                                s_logger.debug("VM " + vmName + " does not have GPU support.");
+                            }
+                            if (vGPUs != null && !vGPUs.isEmpty()) {
+                                HashMap<String, HashMap<String, Long>> groupDetails = getGPUGroupDetails(conn);
+                                cmd.setGpuDevice(new GPUDeviceTO(null, null, groupDetails));
+                            }
+
                             Set<VIF> vifs = vm.getVIFs(conn);
                             List<Network> networks = new ArrayList<Network>();
                             for (VIF vif : vifs) {
@@ -5400,6 +5499,15 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                 details.put("private.network.device", _privateNetworkName);
             }
 
+            try {
+                HashMap<String, HashMap<String, Long>> groupDetails = getGPUGroupDetails(conn);
+                cmd.setGpuGroupDetails(groupDetails);
+            } catch (Exception e) {
+                if (s_logger.isDebugEnabled()) {
+                    s_logger.debug("GPU device not found in host " + hr.hostname);
+                }
+            }
+
             cmd.setHostDetails(details);
             cmd.setName(hr.nameLabel);
             cmd.setGuid(_host.uuid);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java
index b77f8ac..8abb5cd 100755
--- a/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java
+++ b/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java
@@ -26,11 +26,10 @@ import javax.ejb.Local;
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
-import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
-
 import com.cloud.agent.manager.allocator.HostAllocator;
 import com.cloud.capacity.CapacityManager;
 import com.cloud.dc.ClusterDetailsDao;
@@ -38,6 +37,7 @@ import com.cloud.dc.ClusterDetailsVO;
 import com.cloud.dc.dao.ClusterDao;
 import com.cloud.deploy.DeploymentPlan;
 import com.cloud.deploy.DeploymentPlanner.ExcludeList;
+import com.cloud.gpu.GPU;
 import com.cloud.host.DetailVO;
 import com.cloud.host.Host;
 import com.cloud.host.Host.Type;
@@ -47,7 +47,9 @@ import com.cloud.host.dao.HostDetailsDao;
 import com.cloud.offering.ServiceOffering;
 import com.cloud.org.Cluster;
 import com.cloud.resource.ResourceManager;
+import com.cloud.service.ServiceOfferingDetailsVO;
 import com.cloud.service.dao.ServiceOfferingDao;
+import com.cloud.service.dao.ServiceOfferingDetailsDao;
 import com.cloud.storage.GuestOSCategoryVO;
 import com.cloud.storage.GuestOSVO;
 import com.cloud.storage.VMTemplateVO;
@@ -99,6 +101,8 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
     ClusterDao _clusterDao;
     @Inject
     ClusterDetailsDao _clusterDetailsDao;
+    @Inject
+    ServiceOfferingDetailsDao _serviceOfferingDetailsDao;
     float _factor = 1;
     boolean _checkHvm = true;
     protected String _allocationAlgorithm = "random";
@@ -264,7 +268,9 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
             s_logger.debug("Looking for speed=" + (offering.getCpu() * offering.getSpeed()) + "Mhz, Ram=" + offering.getRamSize());
         }
 
+        long serviceOfferingId = offering.getId();
         List<Host> suitableHosts = new ArrayList<Host>();
+        ServiceOfferingDetailsVO offeringDetails = null;
 
         for (Host host : hosts) {
             if (suitableHosts.size() == returnUpTo) {
@@ -286,6 +292,13 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
                 continue;
             }
 
+            // Check if GPU device is required by offering and host has the availability
+            if ((offeringDetails   = _serviceOfferingDetailsDao.findDetail(serviceOfferingId, GPU.Keys.vgpuType.toString())) != null
+                    && !_resourceMgr.isGPUDeviceAvailable(host.getId(), offeringDetails.getValue())){
+                s_logger.info("Host name: " + host.getName() + ", hostId: "+ host.getId() +" does not have required GPU devices available");
+                continue;
+            }
+
             int cpu_requested = offering.getCpu() * offering.getSpeed();
             long ram_requested = offering.getRamSize() * 1024L * 1024L;
             Cluster cluster = _clusterDao.findById(host.getClusterId());

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/server/src/com/cloud/api/ApiDBUtils.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java
index a23244b..539eb70 100755
--- a/server/src/com/cloud/api/ApiDBUtils.java
+++ b/server/src/com/cloud/api/ApiDBUtils.java
@@ -130,6 +130,10 @@ import com.cloud.domain.dao.DomainDao;
 import com.cloud.event.Event;
 import com.cloud.event.dao.EventJoinDao;
 import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.gpu.HostGpuGroupsVO;
+import com.cloud.gpu.VGPUTypesVO;
+import com.cloud.gpu.dao.HostGpuGroupsDao;
+import com.cloud.gpu.dao.VGPUTypesDao;
 import com.cloud.ha.HighAvailabilityManager;
 import com.cloud.host.Host;
 import com.cloud.host.HostStats;
@@ -221,8 +225,10 @@ import com.cloud.server.ResourceTag;
 import com.cloud.server.ResourceTag.ResourceObjectType;
 import com.cloud.server.StatsCollector;
 import com.cloud.server.TaggedResourceService;
+import com.cloud.service.ServiceOfferingDetailsVO;
 import com.cloud.service.ServiceOfferingVO;
 import com.cloud.service.dao.ServiceOfferingDao;
+import com.cloud.service.dao.ServiceOfferingDetailsDao;
 import com.cloud.storage.DiskOfferingVO;
 import com.cloud.storage.GuestOS;
 import com.cloud.storage.GuestOSCategoryVO;
@@ -325,6 +331,7 @@ public class ApiDBUtils {
     static NetworkRuleConfigDao s_networkRuleConfigDao;
     static HostPodDao s_podDao;
     static ServiceOfferingDao s_serviceOfferingDao;
+    static ServiceOfferingDetailsDao s_serviceOfferingDetailsDao;
     static SnapshotDao s_snapshotDao;
     static PrimaryDataStoreDao s_storagePoolDao;
     static VMTemplateDao s_templateDao;
@@ -400,6 +407,8 @@ public class ApiDBUtils {
     static NetworkACLDao s_networkACLDao;
     static AccountService s_accountService;
     static ResourceMetaDataService s_resourceDetailsService;
+    static HostGpuGroupsDao s_hostGpuGroupsDao;
+    static VGPUTypesDao s_vgpuTypesDao;
 
     @Inject
     private ManagementServer ms;
@@ -467,6 +476,8 @@ public class ApiDBUtils {
     @Inject
     private ServiceOfferingDao serviceOfferingDao;
     @Inject
+    private ServiceOfferingDetailsDao serviceOfferingDetailsDao;
+    @Inject
     private SnapshotDao snapshotDao;
     @Inject
     private PrimaryDataStoreDao storagePoolDao;
@@ -616,6 +627,10 @@ public class ApiDBUtils {
     private ConfigurationManager configMgr;
     @Inject
     private ResourceMetaDataService resourceDetailsService;
+    @Inject
+    private HostGpuGroupsDao hostGpuGroupsDao;
+    @Inject
+    private VGPUTypesDao vgpuTypesDao;
 
     @PostConstruct
     void init() {
@@ -649,6 +664,7 @@ public class ApiDBUtils {
         s_networkRuleConfigDao = networkRuleConfigDao;
         s_podDao = podDao;
         s_serviceOfferingDao = serviceOfferingDao;
+        s_serviceOfferingDetailsDao = serviceOfferingDetailsDao;
         s_serviceOfferingJoinDao = serviceOfferingJoinDao;
         s_snapshotDao = snapshotDao;
         s_storagePoolDao = storagePoolDao;
@@ -727,6 +743,8 @@ public class ApiDBUtils {
         s_networkACLDao = networkACLDao;
         s_accountService = accountService;
         s_resourceDetailsService = resourceDetailsService;
+        s_hostGpuGroupsDao = hostGpuGroupsDao;
+        s_vgpuTypesDao = vgpuTypesDao;
 
     }
 
@@ -960,6 +978,10 @@ public class ApiDBUtils {
         return s_serviceOfferingDao.findByIdIncludingRemoved(serviceOfferingId);
     }
 
+    public static ServiceOfferingDetailsVO findServiceOfferingDetail(long serviceOfferingId, String key) {
+        return s_serviceOfferingDetailsDao.findDetail(serviceOfferingId, key);
+    }
+
     public static Snapshot findSnapshotById(long snapshotId) {
         SnapshotVO snapshot = s_snapshotDao.findById(snapshotId);
         if (snapshot != null && snapshot.getRemoved() == null && snapshot.getState() == Snapshot.State.BackedUp) {
@@ -1057,6 +1079,14 @@ public class ApiDBUtils {
         return type;
     }
 
+    public static List<HostGpuGroupsVO> getGpuGroups(long hostId) {
+        return s_hostGpuGroupsDao.listByHostId(hostId);
+    }
+
+    public static List<VGPUTypesVO> getVgpus(long groupId) {
+        return s_vgpuTypesDao.listByGroupId(groupId);
+    }
+
     public static List<UserStatisticsVO> listUserStatsBy(Long accountId) {
         return s_userStatsDao.listBy(accountId);
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java
index 1b95d9b..6c890fc 100644
--- a/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java
@@ -31,12 +31,16 @@ import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
 import org.apache.cloudstack.api.ApiConstants.HostDetails;
+import org.apache.cloudstack.api.response.GpuResponse;
 import org.apache.cloudstack.api.response.HostForMigrationResponse;
 import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.api.response.VgpuResponse;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
 
 import com.cloud.api.ApiDBUtils;
 import com.cloud.api.query.vo.HostJoinVO;
+import com.cloud.gpu.HostGpuGroupsVO;
+import com.cloud.gpu.VGPUTypesVO;
 import com.cloud.host.Host;
 import com.cloud.host.HostStats;
 import com.cloud.storage.StorageStats;
@@ -92,6 +96,27 @@ public class HostJoinDaoImpl extends GenericDaoBase<HostJoinVO, Long> implements
         hostResponse.setVersion(host.getVersion());
         hostResponse.setCreated(host.getCreated());
 
+        List<HostGpuGroupsVO> gpuGroups = ApiDBUtils.getGpuGroups(host.getId());
+        if (gpuGroups != null && !gpuGroups.isEmpty()) {
+            List<GpuResponse> gpus = new ArrayList<GpuResponse>();
+            for (HostGpuGroupsVO entry : gpuGroups) {
+                GpuResponse gpuResponse = new GpuResponse();
+                gpuResponse.setGpuGroupName(entry.getGroupName());
+                List<VGPUTypesVO> vgpuTypes = ApiDBUtils.getVgpus(entry.getId());
+                if (vgpuTypes != null && !vgpuTypes.isEmpty()) {
+                    List<VgpuResponse> vgpus = new ArrayList<VgpuResponse>();
+                    for (VGPUTypesVO vgpuType : vgpuTypes) {
+                        VgpuResponse vgpuResponse = new VgpuResponse();
+                        vgpuResponse.setName(vgpuType.getVgpuType());
+                        vgpuResponse.setCapacity(vgpuType.getRemainingCapacity());
+                        vgpus.add(vgpuResponse);
+                    }
+                    gpuResponse.setVgpu(vgpus);
+                }
+                gpus.add(gpuResponse);
+            }
+            hostResponse.setGpuGroups(gpus);
+        }
         if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity) || details.contains(HostDetails.stats) || details.contains(HostDetails.events)) {
 
             hostResponse.setOsCategoryId(host.getOsCategoryUuid());

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java
index 08478e2..235902c 100644
--- a/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java
@@ -40,7 +40,9 @@ import org.springframework.stereotype.Component;
 import com.cloud.api.ApiDBUtils;
 import com.cloud.api.query.vo.ResourceTagJoinVO;
 import com.cloud.api.query.vo.UserVmJoinVO;
+import com.cloud.gpu.GPU;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.service.ServiceOfferingDetailsVO;
 import com.cloud.user.Account;
 import com.cloud.uservm.UserVm;
 import com.cloud.utils.db.GenericDaoBase;
@@ -157,6 +159,10 @@ public class UserVmJoinDaoImpl extends GenericDaoBase<UserVmJoinVO, Long> implem
             userVmResponse.setCpuNumber(userVm.getCpu());
             userVmResponse.setCpuSpeed(userVm.getSpeed());
             userVmResponse.setMemory(userVm.getRamSize());
+            ServiceOfferingDetailsVO serviceOfferingDetail = ApiDBUtils.findServiceOfferingDetail(userVm.getServiceOfferingId(), GPU.Keys.vgpuType.toString());
+            if (serviceOfferingDetail != null) {
+                userVmResponse.setVgpu(serviceOfferingDetail.getValue());
+            }
         }
         userVmResponse.setGuestOsId(userVm.getGuestOsUuid());
         if (details.contains(VMDetails.all) || details.contains(VMDetails.volume)) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
index 08cc5a6..863d71b 100755
--- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -130,6 +130,7 @@ import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.exception.PermissionDeniedException;
 import com.cloud.exception.ResourceAllocationException;
 import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.gpu.GPU;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.network.IpAddressManager;
 import com.cloud.network.Network;
@@ -2079,13 +2080,56 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
 
         offering.setHypervisorSnapshotReserve(hypervisorSnapshotReserve);
 
-        if ((offering = _serviceOfferingDao.persist(offering)) != null) {
-            if (details != null) {
-                List<ServiceOfferingDetailsVO> detailsVO = new ArrayList<ServiceOfferingDetailsVO>();
-                for (Entry<String, String> detailEntry : details.entrySet()) {
-                    detailsVO.add(new ServiceOfferingDetailsVO(offering.getId(), detailEntry.getKey(), detailEntry.getValue(), true));
+        List<ServiceOfferingDetailsVO> detailsVO = null;
+        if (details != null) {
+            // Check if the user has passed the gpu-type before passing the VGPU type
+            if (!details.containsKey(GPU.Keys.pciDevice.toString()) && details.containsKey(GPU.Keys.vgpuType.toString())) {
+                throw new InvalidParameterValueException("Please specify the gpu type");
+            }
+            detailsVO = new ArrayList<ServiceOfferingDetailsVO>();
+            for (Entry<String, String> detailEntry : details.entrySet()) {
+                String value = null;
+                if (detailEntry.getKey().equals(GPU.Keys.pciDevice.toString())) {
+                    for (GPU.Type type : GPU.Type.values()) {
+                        if (detailEntry.getValue().equals(type.toString())) {
+                            value = detailEntry.getValue();
+                        }
+                    }
+                    if (value == null) {
+                        throw new InvalidParameterValueException("Please specify valid gpu type");
+                    }
+                }
+                if (detailEntry.getKey().equals(GPU.Keys.vgpuType.toString())) {
+                    if (details.get(GPU.Keys.pciDevice.toString()).equals(GPU.Type.GPU_Passthrough.toString())) {
+                        throw new InvalidParameterValueException("vgpuTypes are supported only with vGPU pciDevice");
+                    }
+                    if (detailEntry.getValue() == null) {
+                        throw new InvalidParameterValueException("With vGPU as pciDevice, vGPUType value cannot be null");
+                    }
+                    for (GPU.vGPUType entry : GPU.vGPUType.values()) {
+                        if (detailEntry.getValue().equals(entry.getType())) {
+                            value = entry.getType();
+                        }
+                    }
+                    if (value == null || detailEntry.getValue().equals(GPU.vGPUType.passthrough.getType())) {
+                        throw new InvalidParameterValueException("Please specify valid vGPU type");
+                    }
                 }
+                detailsVO.add(new ServiceOfferingDetailsVO(offering.getId(), detailEntry.getKey(), detailEntry.getValue(), true));
+            }
+            // If pciDevice type is passed, put the default VGPU type as 'passthrough'
+            if (details.containsKey(GPU.Keys.pciDevice.toString())
+                    && !details.containsKey(GPU.Keys.vgpuType.toString())) {
+                detailsVO.add(new ServiceOfferingDetailsVO(offering.getId(),
+                        GPU.Keys.vgpuType.toString(), GPU.vGPUType.passthrough.getType(), true));
+            }
+        }
 
+        if ((offering = _serviceOfferingDao.persist(offering)) != null) {
+            if (detailsVO != null && !detailsVO.isEmpty()) {
+                for (int index = 0; index < detailsVO.size(); index++) {
+                    detailsVO.get(index).setResourceId(offering.getId());
+                }
                 _serviceOfferingDetailsDao.saveDetails(detailsVO);
             }
             CallContext.current().setEventDetails("Service offering id=" + offering.getId());

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java
index 3c87b24..f76e485 100644
--- a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java
+++ b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java
@@ -81,6 +81,7 @@ import com.cloud.deploy.dao.PlannerHostReservationDao;
 import com.cloud.exception.AffinityConflictException;
 import com.cloud.exception.ConnectionException;
 import com.cloud.exception.InsufficientServerCapacityException;
+import com.cloud.gpu.GPU;
 import com.cloud.host.Host;
 import com.cloud.host.HostVO;
 import com.cloud.host.Status;
@@ -89,7 +90,10 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.offering.ServiceOffering;
 import com.cloud.org.Cluster;
 import com.cloud.org.Grouping;
+import com.cloud.resource.ResourceManager;
 import com.cloud.resource.ResourceState;
+import com.cloud.service.ServiceOfferingDetailsVO;
+import com.cloud.service.dao.ServiceOfferingDetailsDao;
 import com.cloud.storage.DiskOfferingVO;
 import com.cloud.storage.ScopeType;
 import com.cloud.storage.Storage;
@@ -213,6 +217,10 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy
     DataStoreManager dataStoreMgr;
     @Inject
     protected ClusterDetailsDao _clusterDetailsDao;
+    @Inject
+    protected ResourceManager _resourceMgr;
+    @Inject
+    protected ServiceOfferingDetailsDao _serviceOfferingDetailsDao;
 
     protected List<DeploymentPlanner> _planners;
 
@@ -353,6 +361,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy
             s_logger.debug("This VM has last host_id specified, trying to choose the same host: " + vm.getLastHostId());
 
             HostVO host = _hostDao.findById(vm.getLastHostId());
+            ServiceOfferingDetailsVO offeringDetails = null;
             if (host == null) {
                 s_logger.debug("The last host of this VM cannot be found");
             } else if (avoids.shouldAvoid(host)) {
@@ -360,6 +369,9 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy
             } else if (_capacityMgr.checkIfHostReachMaxGuestLimit(host)) {
                 s_logger.debug("The last Host, hostId: " + host.getId() +
                     " already has max Running VMs(count includes system VMs), skipping this and trying other available hosts");
+            } else if ((offeringDetails  = _serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.vgpuType.toString())) != null
+                    && !_resourceMgr.isGPUDeviceAvailable(host.getId(), offeringDetails.getValue())){
+                s_logger.debug("The last host of this VM does not have required GPU devices available");
             } else {
                 if (host.getStatus() == Status.Up && host.getResourceState() == ResourceState.Enabled) {
                     boolean hostTagsMatch = true;
@@ -1397,4 +1409,4 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy
         }
         return true;
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c7d31fe2/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
index 7fb79fa..4af20c6 100644
--- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
+++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
@@ -25,8 +25,12 @@ import com.cloud.agent.api.Command;
 import com.cloud.agent.api.to.DiskTO;
 import com.cloud.agent.api.to.NicTO;
 import com.cloud.agent.api.to.VirtualMachineTO;
+import com.cloud.gpu.GPU;
 import com.cloud.offering.ServiceOffering;
+import com.cloud.resource.ResourceManager;
 import com.cloud.server.ConfigurationServer;
+import com.cloud.service.ServiceOfferingDetailsVO;
+import com.cloud.service.dao.ServiceOfferingDetailsDao;
 import com.cloud.storage.dao.VMTemplateDetailsDao;
 import com.cloud.utils.Pair;
 import com.cloud.utils.component.AdapterBase;
@@ -55,6 +59,10 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
     NicSecondaryIpDao _nicSecIpDao;
     @Inject
     ConfigurationServer _configServer;
+    @Inject
+    ResourceManager _resourceMgr;
+    @Inject
+    ServiceOfferingDetailsDao _serviceOfferingDetailsDao;
 
     protected HypervisorGuruBase() {
         super();
@@ -125,6 +133,13 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
         if (detailsInVm != null) {
             to.setDetails(detailsInVm);
         }
+
+        // Set GPU details
+        ServiceOfferingDetailsVO offeringDetail = null;
+        if ((offeringDetail  = _serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.vgpuType.toString())) != null) {
+            to.setGpuDevice(_resourceMgr.getGPUDevice(vm.getHostId(), offeringDetail.getValue()));
+        }
+
         // Workaround to make sure the TO has the UUID we need for Niciri integration
         VMInstanceVO vmInstance = _virtualMachineDao.findById(to.getId());
         // check if XStools/VMWare tools are present in the VM and dynamic scaling feature is enabled (per zone/global)