mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-11-04 00:02:37 +01:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									540d020aa5
								
							
						
					
					
						commit
						c7d31fe288
					
				
							
								
								
									
										56
									
								
								api/src/com/cloud/agent/api/to/GPUDeviceTO.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								api/src/com/cloud/agent/api/to/GPUDeviceTO.java
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										49
									
								
								api/src/com/cloud/gpu/GPU.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								api/src/com/cloud/gpu/GPU.java
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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() {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										46
									
								
								api/src/org/apache/cloudstack/api/response/GpuResponse.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								api/src/org/apache/cloudstack/api/response/GpuResponse.java
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										52
									
								
								api/src/org/apache/cloudstack/api/response/VgpuResponse.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								api/src/org/apache/cloudstack/api/response/VgpuResponse.java
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								core/src/com/cloud/agent/api/GetGPUStatsAnswer.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								core/src/com/cloud/agent/api/GetGPUStatsAnswer.java
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								core/src/com/cloud/agent/api/GetGPUStatsCommand.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								core/src/com/cloud/agent/api/GetGPUStatsCommand.java
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -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" />
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										70
									
								
								engine/schema/src/com/cloud/gpu/HostGpuGroupsVO.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								engine/schema/src/com/cloud/gpu/HostGpuGroupsVO.java
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										82
									
								
								engine/schema/src/com/cloud/gpu/VGPUTypesVO.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								engine/schema/src/com/cloud/gpu/VGPUTypesVO.java
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										60
									
								
								engine/schema/src/com/cloud/gpu/dao/HostGpuGroupsDao.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								engine/schema/src/com/cloud/gpu/dao/HostGpuGroupsDao.java
									
									
									
									
									
										Normal file
									
								
							@ -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);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										48
									
								
								engine/schema/src/com/cloud/gpu/dao/VGPUTypesDao.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								engine/schema/src/com/cloud/gpu/dao/VGPUTypesDao.java
									
									
									
									
									
										Normal file
									
								
							@ -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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										95
									
								
								engine/schema/src/com/cloud/gpu/dao/VGPUTypesDaoImpl.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								engine/schema/src/com/cloud/gpu/dao/VGPUTypesDaoImpl.java
									
									
									
									
									
										Normal file
									
								
							@ -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);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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());
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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());
 | 
			
		||||
 | 
			
		||||
@ -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)) {
 | 
			
		||||
 | 
			
		||||
@ -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());
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
 | 
			
		||||
@ -57,6 +57,7 @@ import com.cloud.event.UsageEventVO;
 | 
			
		||||
import com.cloud.event.dao.UsageEventDao;
 | 
			
		||||
import com.cloud.exception.AgentUnavailableException;
 | 
			
		||||
import com.cloud.exception.InvalidParameterValueException;
 | 
			
		||||
import com.cloud.gpu.dao.HostGpuGroupsDao;
 | 
			
		||||
import com.cloud.host.DetailVO;
 | 
			
		||||
import com.cloud.host.Host;
 | 
			
		||||
import com.cloud.host.HostVO;
 | 
			
		||||
@ -116,6 +117,8 @@ public class NetworkUsageManagerImpl extends ManagerBase implements NetworkUsage
 | 
			
		||||
    @Inject
 | 
			
		||||
    HostDetailsDao _detailsDao;
 | 
			
		||||
    @Inject
 | 
			
		||||
    HostGpuGroupsDao _hostGpuGroupsDao;
 | 
			
		||||
    @Inject
 | 
			
		||||
    AccountManager _accountMgr;
 | 
			
		||||
    @Inject
 | 
			
		||||
    NetworkDao _networksDao = null;
 | 
			
		||||
@ -537,6 +540,7 @@ public class NetworkUsageManagerImpl extends ManagerBase implements NetworkUsage
 | 
			
		||||
        long hostId = host.getId();
 | 
			
		||||
        _agentMgr.disconnectWithoutInvestigation(hostId, Status.Event.Remove);
 | 
			
		||||
        _detailsDao.deleteDetails(hostId);
 | 
			
		||||
        _hostGpuGroupsDao.deleteGpuEntries(hostId);
 | 
			
		||||
        host.setGuid(null);
 | 
			
		||||
        _hostDao.update(hostId, host);
 | 
			
		||||
        _hostDao.remove(hostId);
 | 
			
		||||
 | 
			
		||||
@ -30,11 +30,6 @@ import javax.ejb.Local;
 | 
			
		||||
import javax.inject.Inject;
 | 
			
		||||
import javax.naming.ConfigurationException;
 | 
			
		||||
 | 
			
		||||
import org.apache.log4j.Logger;
 | 
			
		||||
import org.springframework.stereotype.Component;
 | 
			
		||||
 | 
			
		||||
import com.google.gson.Gson;
 | 
			
		||||
 | 
			
		||||
import org.apache.cloudstack.api.ApiConstants;
 | 
			
		||||
import org.apache.cloudstack.api.command.admin.cluster.AddClusterCmd;
 | 
			
		||||
import org.apache.cloudstack.api.command.admin.cluster.DeleteClusterCmd;
 | 
			
		||||
@ -51,10 +46,14 @@ import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 | 
			
		||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
 | 
			
		||||
import org.apache.cloudstack.utils.identity.ManagementServerNode;
 | 
			
		||||
import org.apache.commons.lang.ObjectUtils;
 | 
			
		||||
import org.apache.log4j.Logger;
 | 
			
		||||
import org.springframework.stereotype.Component;
 | 
			
		||||
 | 
			
		||||
import com.cloud.agent.AgentManager;
 | 
			
		||||
import com.cloud.agent.api.Answer;
 | 
			
		||||
import com.cloud.agent.api.Command;
 | 
			
		||||
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.MaintainAnswer;
 | 
			
		||||
@ -64,6 +63,7 @@ import com.cloud.agent.api.StartupCommand;
 | 
			
		||||
import com.cloud.agent.api.StartupRoutingCommand;
 | 
			
		||||
import com.cloud.agent.api.UnsupportedAnswer;
 | 
			
		||||
import com.cloud.agent.api.UpdateHostPasswordCommand;
 | 
			
		||||
import com.cloud.agent.api.to.GPUDeviceTO;
 | 
			
		||||
import com.cloud.agent.transport.Request;
 | 
			
		||||
import com.cloud.api.ApiDBUtils;
 | 
			
		||||
import com.cloud.capacity.Capacity;
 | 
			
		||||
@ -97,6 +97,11 @@ import com.cloud.exception.DiscoveryException;
 | 
			
		||||
import com.cloud.exception.InvalidParameterValueException;
 | 
			
		||||
import com.cloud.exception.PermissionDeniedException;
 | 
			
		||||
import com.cloud.exception.ResourceInUseException;
 | 
			
		||||
import com.cloud.gpu.GPU.vGPUType;
 | 
			
		||||
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.ha.HighAvailabilityManager.WorkType;
 | 
			
		||||
import com.cloud.host.DetailVO;
 | 
			
		||||
@ -137,11 +142,14 @@ import com.cloud.utils.UriUtils;
 | 
			
		||||
import com.cloud.utils.component.Manager;
 | 
			
		||||
import com.cloud.utils.component.ManagerBase;
 | 
			
		||||
import com.cloud.utils.db.DB;
 | 
			
		||||
import com.cloud.utils.db.Filter;
 | 
			
		||||
import com.cloud.utils.db.GenericSearchBuilder;
 | 
			
		||||
import com.cloud.utils.db.GlobalLock;
 | 
			
		||||
import com.cloud.utils.db.JoinBuilder;
 | 
			
		||||
import com.cloud.utils.db.QueryBuilder;
 | 
			
		||||
import com.cloud.utils.db.SearchBuilder;
 | 
			
		||||
import com.cloud.utils.db.SearchCriteria;
 | 
			
		||||
import com.cloud.utils.db.TransactionLegacy;
 | 
			
		||||
import com.cloud.utils.db.SearchCriteria.Func;
 | 
			
		||||
import com.cloud.utils.db.SearchCriteria.Op;
 | 
			
		||||
import com.cloud.utils.db.Transaction;
 | 
			
		||||
@ -158,6 +166,7 @@ import com.cloud.vm.VMInstanceVO;
 | 
			
		||||
import com.cloud.vm.VirtualMachine.State;
 | 
			
		||||
import com.cloud.vm.VirtualMachineManager;
 | 
			
		||||
import com.cloud.vm.dao.VMInstanceDao;
 | 
			
		||||
import com.google.gson.Gson;
 | 
			
		||||
 | 
			
		||||
@Component
 | 
			
		||||
@Local({ResourceManager.class, ResourceService.class})
 | 
			
		||||
@ -193,6 +202,10 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
 | 
			
		||||
    @Inject
 | 
			
		||||
    private GuestOSCategoryDao _guestOSCategoryDao;
 | 
			
		||||
    @Inject
 | 
			
		||||
    protected HostGpuGroupsDao _hostGpuGroupsDao;
 | 
			
		||||
    @Inject
 | 
			
		||||
    protected VGPUTypesDao _vgpuTypesDao;
 | 
			
		||||
    @Inject
 | 
			
		||||
    private PrimaryDataStoreDao _storagePoolDao;
 | 
			
		||||
    @Inject
 | 
			
		||||
    private DataCenterIpAddressDao _privateIPAddressDao;
 | 
			
		||||
@ -244,6 +257,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
 | 
			
		||||
 | 
			
		||||
    private GenericSearchBuilder<HostVO, String> _hypervisorsInDC;
 | 
			
		||||
 | 
			
		||||
    private SearchBuilder<HostGpuGroupsVO> _gpuAvailability;
 | 
			
		||||
 | 
			
		||||
    private void insertListener(Integer event, ResourceListener listener) {
 | 
			
		||||
        List<ResourceListener> lst = _lifeCycleListeners.get(event);
 | 
			
		||||
        if (lst == null) {
 | 
			
		||||
@ -827,6 +842,9 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
 | 
			
		||||
                // delete host details
 | 
			
		||||
                _hostDetailsDao.deleteDetails(hostId);
 | 
			
		||||
 | 
			
		||||
                // if host is GPU enabled, delete GPU entries
 | 
			
		||||
                _hostGpuGroupsDao.deleteGpuEntries(hostId);
 | 
			
		||||
 | 
			
		||||
                host.setGuid(null);
 | 
			
		||||
                Long clusterId = host.getClusterId();
 | 
			
		||||
                host.setClusterId(null);
 | 
			
		||||
@ -1329,6 +1347,14 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
 | 
			
		||||
        _hypervisorsInDC.and("type", _hypervisorsInDC.entity().getType(), SearchCriteria.Op.EQ);
 | 
			
		||||
        _hypervisorsInDC.done();
 | 
			
		||||
 | 
			
		||||
        _gpuAvailability = _hostGpuGroupsDao.createSearchBuilder();
 | 
			
		||||
        _gpuAvailability.and("hostId", _gpuAvailability.entity().getHostId(), Op.EQ);
 | 
			
		||||
        SearchBuilder<VGPUTypesVO> join1 = _vgpuTypesDao.createSearchBuilder();
 | 
			
		||||
        join1.and("vgpuType", join1.entity().getVgpuType(), Op.EQ);
 | 
			
		||||
        join1.and("remainingCapacity", join1.entity().getRemainingCapacity(), Op.GT);
 | 
			
		||||
        _gpuAvailability.join("groupId", join1, _gpuAvailability.entity().getId(), join1.entity().getGpuGroupId(), JoinBuilder.JoinType.INNER);
 | 
			
		||||
        _gpuAvailability.done();
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1958,6 +1984,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
 | 
			
		||||
        host.setSpeed(ssCmd.getSpeed());
 | 
			
		||||
        host.setHypervisorType(hyType);
 | 
			
		||||
        host.setHypervisorVersion(ssCmd.getHypervisorVersion());
 | 
			
		||||
        host.setGpuGroups(ssCmd.getGpuGroupDetails());
 | 
			
		||||
        return host;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -2473,6 +2500,66 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
 | 
			
		||||
        return sc.list();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<HostGpuGroupsVO> listAvailableGPUDevice(long hostId, String vgpuType) {
 | 
			
		||||
        if (vgpuType == null) {
 | 
			
		||||
            vgpuType = vGPUType.passthrough.getType();
 | 
			
		||||
        }
 | 
			
		||||
        Filter searchFilter = new Filter(VGPUTypesVO.class, "remainingCapacity", false, null, null);
 | 
			
		||||
        SearchCriteria<HostGpuGroupsVO> sc = _gpuAvailability.create();
 | 
			
		||||
        sc.setParameters("hostId", hostId);
 | 
			
		||||
        sc.setJoinParameters("groupId", "vgpuType", vgpuType);
 | 
			
		||||
        sc.setJoinParameters("groupId", "remainingCapacity", 0);
 | 
			
		||||
        return _hostGpuGroupsDao.customSearch(sc, searchFilter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isGPUDeviceAvailable(long hostId, String vgpuType) {
 | 
			
		||||
        if(!listAvailableGPUDevice(hostId, vgpuType).isEmpty()) {
 | 
			
		||||
            return true;
 | 
			
		||||
        } else {
 | 
			
		||||
            if (s_logger.isDebugEnabled()) {
 | 
			
		||||
                s_logger.debug("Host ID: "+ hostId +" does not have GPU device available");
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public GPUDeviceTO getGPUDevice(long hostId, String vgpuType) {
 | 
			
		||||
        HostGpuGroupsVO gpuDevice = listAvailableGPUDevice(hostId, vgpuType).get(0);
 | 
			
		||||
        return new GPUDeviceTO(gpuDevice.getGroupName(), vgpuType, null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void updateGPUDetails(long hostId, HashMap<String, HashMap<String, Long>> groupDetails) {
 | 
			
		||||
        // Update GPU group capacity
 | 
			
		||||
        TransactionLegacy txn = TransactionLegacy.currentTxn();
 | 
			
		||||
        txn.start();
 | 
			
		||||
        _hostGpuGroupsDao.persist(hostId, new ArrayList<String>(groupDetails.keySet()));
 | 
			
		||||
        _vgpuTypesDao.persist(hostId, groupDetails);
 | 
			
		||||
        txn.commit();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public HashMap<String, HashMap<String, Long>> getGPUStatistics(HostVO host) {
 | 
			
		||||
        Answer answer = _agentMgr.easySend(host.getId(), new GetGPUStatsCommand(host.getGuid(), host.getName()));
 | 
			
		||||
        if (answer != null && (answer instanceof UnsupportedAnswer)) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        if (answer == null || !answer.getResult()) {
 | 
			
		||||
            String msg = "Unable to obtain GPU stats for host " + host.getName();
 | 
			
		||||
            s_logger.warn(msg);
 | 
			
		||||
            return null;
 | 
			
		||||
        } else {
 | 
			
		||||
            // now construct the result object
 | 
			
		||||
            if (answer instanceof GetGPUStatsAnswer) {
 | 
			
		||||
                return ((GetGPUStatsAnswer)answer).getGroupDetails();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @DB
 | 
			
		||||
    @ActionEvent(eventType = EventTypes.EVENT_HOST_RESERVATION_RELEASE, eventDescription = "releasing host reservation", async = true)
 | 
			
		||||
 | 
			
		||||
@ -508,6 +508,7 @@ import com.cloud.exception.OperationTimedoutException;
 | 
			
		||||
import com.cloud.exception.PermissionDeniedException;
 | 
			
		||||
import com.cloud.exception.ResourceUnavailableException;
 | 
			
		||||
import com.cloud.exception.VirtualMachineMigrationException;
 | 
			
		||||
import com.cloud.gpu.GPU;
 | 
			
		||||
import com.cloud.ha.HighAvailabilityManager;
 | 
			
		||||
import com.cloud.host.DetailVO;
 | 
			
		||||
import com.cloud.host.Host;
 | 
			
		||||
@ -539,6 +540,7 @@ import com.cloud.server.ResourceTag.ResourceObjectType;
 | 
			
		||||
import com.cloud.server.auth.UserAuthenticator;
 | 
			
		||||
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;
 | 
			
		||||
@ -700,6 +702,9 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
 | 
			
		||||
    private ResourceTagDao _resourceTagDao;
 | 
			
		||||
    @Inject
 | 
			
		||||
    private ImageStoreDao _imgStoreDao;
 | 
			
		||||
    @Inject
 | 
			
		||||
    private ServiceOfferingDetailsDao _serviceOfferingDetailsDao;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Inject
 | 
			
		||||
    private ProjectManager _projectMgr;
 | 
			
		||||
@ -1059,6 +1064,13 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
 | 
			
		||||
            throw ex;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(_serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) {
 | 
			
		||||
            s_logger.info(" Live Migration of GPU enabled VM : " + vm.getInstanceName()+ " is not supported");
 | 
			
		||||
            // Return empty list.
 | 
			
		||||
            return new Ternary<Pair<List<? extends Host>, Integer>, List<? extends Host>, Map<Host, Boolean>>(new Pair<List <? extends Host>,
 | 
			
		||||
                    Integer>(new ArrayList<HostVO>(), new Integer(0)), new ArrayList<Host>(), new HashMap<Host, Boolean>());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!vm.getHypervisorType().equals(HypervisorType.XenServer) && !vm.getHypervisorType().equals(HypervisorType.VMware) && !vm.getHypervisorType().equals(HypervisorType.KVM)
 | 
			
		||||
                && !vm.getHypervisorType().equals(HypervisorType.Ovm) && !vm.getHypervisorType().equals(HypervisorType.Hyperv)) {
 | 
			
		||||
            if (s_logger.isDebugEnabled()) {
 | 
			
		||||
 | 
			
		||||
@ -54,6 +54,7 @@ import com.cloud.agent.api.VmStatsEntry;
 | 
			
		||||
import com.cloud.cluster.ManagementServerHostVO;
 | 
			
		||||
import com.cloud.cluster.dao.ManagementServerHostDao;
 | 
			
		||||
import com.cloud.exception.StorageUnavailableException;
 | 
			
		||||
import com.cloud.gpu.dao.HostGpuGroupsDao;
 | 
			
		||||
import com.cloud.host.Host;
 | 
			
		||||
import com.cloud.host.HostStats;
 | 
			
		||||
import com.cloud.host.HostVO;
 | 
			
		||||
@ -175,6 +176,8 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
 | 
			
		||||
    private AutoScaleVmProfileDao _asProfileDao;
 | 
			
		||||
    @Inject
 | 
			
		||||
    private ServiceOfferingDao _serviceOfferingDao;
 | 
			
		||||
    @Inject
 | 
			
		||||
    private HostGpuGroupsDao _hostGpuGroupsDao;
 | 
			
		||||
 | 
			
		||||
    private ConcurrentHashMap<Long, HostStats> _hostStats = new ConcurrentHashMap<Long, HostStats>();
 | 
			
		||||
    private final ConcurrentHashMap<Long, VmStats> _VmStats = new ConcurrentHashMap<Long, VmStats>();
 | 
			
		||||
@ -188,6 +191,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
 | 
			
		||||
    long volumeStatsInterval = -1L;
 | 
			
		||||
    long autoScaleStatsInterval = -1L;
 | 
			
		||||
    int vmDiskStatsInterval = 0;
 | 
			
		||||
    List<Long> hostIds = null;
 | 
			
		||||
 | 
			
		||||
    private ScheduledExecutorService _diskStatsUpdateExecutor;
 | 
			
		||||
    private int _usageAggregationRange = 1440;
 | 
			
		||||
@ -325,6 +329,23 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                _hostStats = hostStats;
 | 
			
		||||
                // Get a subset of hosts with GPU support from the list of "hosts"
 | 
			
		||||
                List<HostVO> gpuEnabledHosts = new ArrayList<HostVO>();
 | 
			
		||||
                if (hostIds != null) {
 | 
			
		||||
                    for (HostVO host : hosts) {
 | 
			
		||||
                        if (hostIds.contains(host.getId())) {
 | 
			
		||||
                            gpuEnabledHosts.add(host);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    // Check for all the hosts managed by CloudStack.
 | 
			
		||||
                    gpuEnabledHosts = hosts;
 | 
			
		||||
                }
 | 
			
		||||
                for (HostVO host : gpuEnabledHosts) {
 | 
			
		||||
                    HashMap<String, HashMap<String, Long>> groupDetails = _resourceMgr.getGPUStatistics(host);
 | 
			
		||||
                    _resourceMgr.updateGPUDetails(host.getId(), groupDetails);
 | 
			
		||||
                }
 | 
			
		||||
                hostIds = _hostGpuGroupsDao.listHostIds();
 | 
			
		||||
            } catch (Throwable t) {
 | 
			
		||||
                s_logger.error("Error trying to retrieve host stats", t);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -92,12 +92,14 @@ import com.cloud.exception.InvalidParameterValueException;
 | 
			
		||||
import com.cloud.exception.PermissionDeniedException;
 | 
			
		||||
import com.cloud.exception.ResourceAllocationException;
 | 
			
		||||
import com.cloud.exception.StorageUnavailableException;
 | 
			
		||||
import com.cloud.gpu.GPU;
 | 
			
		||||
import com.cloud.host.HostVO;
 | 
			
		||||
import com.cloud.host.dao.HostDao;
 | 
			
		||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
 | 
			
		||||
import com.cloud.hypervisor.HypervisorCapabilitiesVO;
 | 
			
		||||
import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
 | 
			
		||||
import com.cloud.org.Grouping;
 | 
			
		||||
import com.cloud.service.dao.ServiceOfferingDetailsDao;
 | 
			
		||||
import com.cloud.storage.Storage.ImageFormat;
 | 
			
		||||
import com.cloud.storage.dao.DiskOfferingDao;
 | 
			
		||||
import com.cloud.storage.dao.SnapshotDao;
 | 
			
		||||
@ -171,6 +173,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
 | 
			
		||||
    @Inject
 | 
			
		||||
    private SnapshotDao _snapshotDao;
 | 
			
		||||
    @Inject
 | 
			
		||||
    protected ServiceOfferingDetailsDao _serviceOfferingDetailsDao;
 | 
			
		||||
    @Inject
 | 
			
		||||
    StoragePoolDetailsDao storagePoolDetailsDao;
 | 
			
		||||
    @Inject
 | 
			
		||||
    private UserVmDao _userVmDao;
 | 
			
		||||
@ -1466,6 +1470,10 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (vm != null && vm.getState() == State.Running) {
 | 
			
		||||
            // Check if the VM is GPU enabled.
 | 
			
		||||
            if(_serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) {
 | 
			
		||||
                throw new InvalidParameterValueException("Live Migration of GPU enabled VM is not supported");
 | 
			
		||||
            }
 | 
			
		||||
            // Check if the underlying hypervisor supports storage motion.
 | 
			
		||||
            Long hostId = vm.getHostId();
 | 
			
		||||
            if (hostId != null) {
 | 
			
		||||
 | 
			
		||||
@ -137,6 +137,7 @@ import com.cloud.exception.ResourceAllocationException;
 | 
			
		||||
import com.cloud.exception.ResourceUnavailableException;
 | 
			
		||||
import com.cloud.exception.StorageUnavailableException;
 | 
			
		||||
import com.cloud.exception.VirtualMachineMigrationException;
 | 
			
		||||
import com.cloud.gpu.GPU;
 | 
			
		||||
import com.cloud.ha.HighAvailabilityManager;
 | 
			
		||||
import com.cloud.host.Host;
 | 
			
		||||
import com.cloud.host.HostVO;
 | 
			
		||||
@ -3853,6 +3854,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
 | 
			
		||||
            ex.addProxyObject(vm.getUuid(), "vmId");
 | 
			
		||||
            throw ex;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) {
 | 
			
		||||
            throw new InvalidParameterValueException("Live Migration of GPU enabled VM is not supported");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!vm.getHypervisorType().equals(HypervisorType.XenServer) && !vm.getHypervisorType().equals(HypervisorType.VMware) && !vm.getHypervisorType().equals(HypervisorType.KVM)
 | 
			
		||||
                && !vm.getHypervisorType().equals(HypervisorType.Ovm) && !vm.getHypervisorType().equals(HypervisorType.Hyperv)
 | 
			
		||||
                && !vm.getHypervisorType().equals(HypervisorType.Simulator)) {
 | 
			
		||||
@ -4164,6 +4170,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
 | 
			
		||||
            throw ex;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.pciDevice.toString()) != null) {
 | 
			
		||||
            throw new InvalidParameterValueException("Live Migration of GPU enabled VM is not supported");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!vm.getHypervisorType().equals(HypervisorType.XenServer) && !vm.getHypervisorType().equals(HypervisorType.VMware) && !vm.getHypervisorType().equals(HypervisorType.KVM)
 | 
			
		||||
                && !vm.getHypervisorType().equals(HypervisorType.Ovm) && !vm.getHypervisorType().equals(HypervisorType.Simulator)) {
 | 
			
		||||
            throw new InvalidParameterValueException("Unsupported hypervisor type for vm migration, we support" + " XenServer/VMware/KVM only");
 | 
			
		||||
 | 
			
		||||
@ -17,6 +17,7 @@
 | 
			
		||||
 | 
			
		||||
package com.cloud.resource;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
@ -35,6 +36,7 @@ import org.apache.cloudstack.api.command.admin.host.UpdateHostPasswordCmd;
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
@ -42,6 +44,7 @@ import com.cloud.exception.AgentUnavailableException;
 | 
			
		||||
import com.cloud.exception.DiscoveryException;
 | 
			
		||||
import com.cloud.exception.InvalidParameterValueException;
 | 
			
		||||
import com.cloud.exception.ResourceInUseException;
 | 
			
		||||
import com.cloud.gpu.HostGpuGroupsVO;
 | 
			
		||||
import com.cloud.host.Host;
 | 
			
		||||
import com.cloud.host.Host.Type;
 | 
			
		||||
import com.cloud.host.HostStats;
 | 
			
		||||
@ -554,4 +557,32 @@ public class MockResourceManagerImpl extends ManagerBase implements ResourceMana
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isGPUDeviceAvailable(long hostId, String vgpuType) {
 | 
			
		||||
        // TODO Auto-generated method stub
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public GPUDeviceTO getGPUDevice(long hostId, String vgpuType) {
 | 
			
		||||
        // TODO Auto-generated method stub
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<HostGpuGroupsVO> listAvailableGPUDevice(long hostId, String vgpuType) {
 | 
			
		||||
        // TODO Auto-generated method stub
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void updateGPUDetails(long hostId, HashMap<String, HashMap<String, Long>> deviceDetails) {
 | 
			
		||||
        // TODO Auto-generated method stub
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public HashMap<String, HashMap<String, Long>> getGPUStatistics(HostVO host) {
 | 
			
		||||
        // TODO Auto-generated method stub
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -78,7 +78,9 @@ import com.cloud.exception.AffinityConflictException;
 | 
			
		||||
import com.cloud.exception.InsufficientServerCapacityException;
 | 
			
		||||
import com.cloud.host.dao.HostDao;
 | 
			
		||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
 | 
			
		||||
import com.cloud.resource.ResourceManager;
 | 
			
		||||
import com.cloud.service.ServiceOfferingVO;
 | 
			
		||||
import com.cloud.service.dao.ServiceOfferingDetailsDao;
 | 
			
		||||
import com.cloud.storage.StorageManager;
 | 
			
		||||
import com.cloud.storage.dao.DiskOfferingDao;
 | 
			
		||||
import com.cloud.storage.dao.GuestOSCategoryDao;
 | 
			
		||||
@ -238,6 +240,16 @@ public class DeploymentPlanningManagerImplTest {
 | 
			
		||||
            return Mockito.mock(ClusterDetailsDao.class);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Bean
 | 
			
		||||
        public ResourceManager resourceManager() {
 | 
			
		||||
            return Mockito.mock(ResourceManager.class);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Bean
 | 
			
		||||
        public ServiceOfferingDetailsDao serviceOfferingDetailsDao() {
 | 
			
		||||
            return Mockito.mock(ServiceOfferingDetailsDao.class);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @Bean
 | 
			
		||||
        public DataStoreManager cataStoreManager() {
 | 
			
		||||
            return Mockito.mock(DataStoreManager.class);
 | 
			
		||||
 | 
			
		||||
@ -43,7 +43,9 @@
 | 
			
		||||
    </bean>
 | 
			
		||||
 | 
			
		||||
    <bean class="org.apache.cloudstack.networkoffering.ChildTestConfiguration" />
 | 
			
		||||
    <bean id="UservmDetailsDaoImpl" class="com.cloud.vm.dao.UserVmDetailsDaoImpl" />
 | 
			
		||||
    <bean id="UservmDetailsDaoImpl" class="com.cloud.vm.dao.UserVmDetailsDaoImpl" />
 | 
			
		||||
    <bean id="hostGpuGroupsDaoImpl" class="com.cloud.gpu.dao.HostGpuGroupsDaoImpl" />
 | 
			
		||||
    <bean id="vGPUTypesDaoImpl" class="com.cloud.gpu.dao.VGPUTypesDaoImpl" />
 | 
			
		||||
    <bean id="usageEventDaoImpl" class="com.cloud.event.dao.UsageEventDaoImpl" />
 | 
			
		||||
    <bean id="usageEventDetailsDaoImpl" class="com.cloud.event.dao.UsageEventDetailsDaoImpl" />
 | 
			
		||||
</beans>
 | 
			
		||||
 | 
			
		||||
@ -592,4 +592,22 @@ CREATE VIEW `cloud`.`event_view` AS
 | 
			
		||||
        `cloud`.`event` eve ON event.start_id = eve.id;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `cloud`.`host_gpu_groups`;
 | 
			
		||||
CREATE TABLE `cloud`.`host_gpu_groups` (
 | 
			
		||||
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
 | 
			
		||||
  `group_name` varchar(255) NOT NULL,
 | 
			
		||||
  `host_id` bigint(20) unsigned NOT NULL,
 | 
			
		||||
  PRIMARY KEY (`id`),
 | 
			
		||||
  CONSTRAINT `fk_host_gpu_groups__host_id` FOREIGN KEY (`host_id`) REFERENCES `host` (`id`) ON DELETE CASCADE
 | 
			
		||||
) ENGINE=InnoDB CHARSET=utf8;
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `cloud`.`vgpu_types`;
 | 
			
		||||
CREATE TABLE `cloud`.`vgpu_types` (
 | 
			
		||||
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
 | 
			
		||||
  `gpu_group_id` bigint(20) unsigned NOT NULL,
 | 
			
		||||
  `vgpu_type` varchar(40) NOT NULL COMMENT 'vgpu type supported by this gpu group',
 | 
			
		||||
  `remaining_vm_capacity` bigint(20) unsigned DEFAULT NULL COMMENT 'remaining vgpu can be created with this vgpu_type on the given gpu group',
 | 
			
		||||
  PRIMARY KEY (`id`),
 | 
			
		||||
  CONSTRAINT `fk_vgpu_types__gpu_group_id` FOREIGN KEY (`gpu_group_id`) REFERENCES `host_gpu_groups` (`id`) ON DELETE CASCADE
 | 
			
		||||
) ENGINE=InnoDB CHARSET=utf8;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										227
									
								
								test/integration/smoke/test_deploy_vgpu_enabled_vm.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								test/integration/smoke/test_deploy_vgpu_enabled_vm.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,227 @@
 | 
			
		||||
# 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.
 | 
			
		||||
 | 
			
		||||
#Test from the Marvin - Testing in Python wiki
 | 
			
		||||
 | 
			
		||||
#All tests inherit from cloudstackTestCase
 | 
			
		||||
from marvin.cloudstackTestCase import cloudstackTestCase
 | 
			
		||||
 | 
			
		||||
#Import Integration Libraries
 | 
			
		||||
 | 
			
		||||
#base - contains all resources as entities and defines create, delete, list operations on them
 | 
			
		||||
from marvin.integration.lib.base import Account, VirtualMachine, ServiceOffering
 | 
			
		||||
 | 
			
		||||
#utils - utility classes for common cleanup, external library wrappers etc
 | 
			
		||||
from marvin.integration.lib.utils import cleanup_resources
 | 
			
		||||
 | 
			
		||||
#common - commonly used methods for all tests are listed here
 | 
			
		||||
from marvin.integration.lib.common import get_zone, get_domain, get_template
 | 
			
		||||
 | 
			
		||||
from nose.plugins.attrib import attr
 | 
			
		||||
 | 
			
		||||
class Services:
 | 
			
		||||
    """Test VM Life Cycle Services
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.services = {
 | 
			
		||||
                "disk_offering":{
 | 
			
		||||
                    "displaytext": "Small",
 | 
			
		||||
                    "name": "Small",
 | 
			
		||||
                    "disksize": 1
 | 
			
		||||
                },
 | 
			
		||||
                "account": {
 | 
			
		||||
                    "email": "test@test.com",
 | 
			
		||||
                    "firstname": "Test",
 | 
			
		||||
                    "lastname": "User",
 | 
			
		||||
                    "username": "test",
 | 
			
		||||
                    # Random characters are appended in create account to
 | 
			
		||||
                    # ensure unique username generated each time
 | 
			
		||||
                    "password": "password",
 | 
			
		||||
                },
 | 
			
		||||
                "vgpu260q":   # Create a virtual machine instance with vgpu type as 260q
 | 
			
		||||
                {
 | 
			
		||||
                    "displayname": "testserver",
 | 
			
		||||
                    "username": "root", # VM creds for SSH
 | 
			
		||||
                    "password": "password",
 | 
			
		||||
                    "ssh_port": 22,
 | 
			
		||||
                    "hypervisor": 'XenServer',
 | 
			
		||||
                    "privateport": 22,
 | 
			
		||||
                    "publicport": 22,
 | 
			
		||||
                    "protocol": 'TCP',
 | 
			
		||||
                },
 | 
			
		||||
                "vgpu140q":   # Create a virtual machine instance with vgpu type as 140q
 | 
			
		||||
                {
 | 
			
		||||
                    "displayname": "testserver",
 | 
			
		||||
                    "username": "root",
 | 
			
		||||
                    "password": "password",
 | 
			
		||||
                    "ssh_port": 22,
 | 
			
		||||
                    "hypervisor": 'XenServer',
 | 
			
		||||
                    "privateport": 22,
 | 
			
		||||
                    "publicport": 22,
 | 
			
		||||
                    "protocol": 'TCP',
 | 
			
		||||
                },
 | 
			
		||||
                "service_offerings":
 | 
			
		||||
                {
 | 
			
		||||
                 "vgpu260qwin":
 | 
			
		||||
                   {
 | 
			
		||||
                        "name": "Windows Instance with vGPU260Q",
 | 
			
		||||
                        "displaytext": "Windows Instance with vGPU260Q",
 | 
			
		||||
                        "cpunumber": 2,
 | 
			
		||||
                        "cpuspeed": 1600, # in MHz
 | 
			
		||||
                        "memory": 3072, # In MBs
 | 
			
		||||
                    },
 | 
			
		||||
                 "vgpu140qwin":
 | 
			
		||||
                    {
 | 
			
		||||
                     # Small service offering ID to for change VM
 | 
			
		||||
                     # service offering from medium to small
 | 
			
		||||
                        "name": "Windows Instance with vGPU140Q",
 | 
			
		||||
                        "displaytext": "Windows Instance with vGPU140Q",
 | 
			
		||||
                        "cpunumber": 2,
 | 
			
		||||
                        "cpuspeed": 1600,
 | 
			
		||||
                        "memory": 3072,
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
            "diskdevice": ['/dev/vdc',  '/dev/vdb', '/dev/hdb', '/dev/hdc', '/dev/xvdd', '/dev/cdrom', '/dev/sr0', '/dev/cdrom1' ],
 | 
			
		||||
            # Disk device where ISO is attached to instance
 | 
			
		||||
            "mount_dir": "/mnt/tmp",
 | 
			
		||||
            "sleep": 60,
 | 
			
		||||
            "timeout": 10,
 | 
			
		||||
            #Migrate VM to hostid
 | 
			
		||||
            "ostype": 'Windows 7 (32-bit)',
 | 
			
		||||
            # CentOS 5.3 (64-bit)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestDeployvGPUenabledVM(cloudstackTestCase):
 | 
			
		||||
    """Test deploy a vGPU enabled VM into a user account
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        self.services = Services().services
 | 
			
		||||
        self.apiclient = self.testClient.getApiClient()
 | 
			
		||||
 | 
			
		||||
        # Get Zone, Domain and Default Built-in template
 | 
			
		||||
        self.domain = get_domain(self.apiclient, self.services)
 | 
			
		||||
        self.zone = get_zone(self.apiclient, self.services)
 | 
			
		||||
        self.services["mode"] = self.zone.networktype
 | 
			
		||||
        # Before running this test, register a windows template with ostype as 'Windows 7 (32-bit)'
 | 
			
		||||
        self.template = get_template(self.apiclient, self.zone.id, self.services["ostype"], templatetype='USER')
 | 
			
		||||
 | 
			
		||||
        #create a user account
 | 
			
		||||
        self.account = Account.create(
 | 
			
		||||
            self.apiclient,
 | 
			
		||||
            self.services["account"],
 | 
			
		||||
            domainid=self.domain.id
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        self.services["vgpu260q"]["zoneid"] = self.zone.id
 | 
			
		||||
        self.services["vgpu260q"]["template"] = self.template.id
 | 
			
		||||
 | 
			
		||||
        self.services["vgpu140q"]["zoneid"] = self.zone.id
 | 
			
		||||
        self.services["vgpu140q"]["template"] = self.template.id
 | 
			
		||||
        #create a service offering
 | 
			
		||||
        self.service_offering = ServiceOffering.create(
 | 
			
		||||
                self.apiclient,
 | 
			
		||||
                self.services["service_offerings"]["vgpu260qwin"],
 | 
			
		||||
                serviceofferingdetails={'pciDevice': 'VGPU'}
 | 
			
		||||
        )
 | 
			
		||||
        #build cleanup list
 | 
			
		||||
        self.cleanup = [
 | 
			
		||||
            self.service_offering,
 | 
			
		||||
            self.account
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
    @attr(tags = ['advanced', 'simulator', 'basic', 'vgpu'])
 | 
			
		||||
    def test_deploy_vgpu_enabled_vm(self):
 | 
			
		||||
        """Test Deploy Virtual Machine
 | 
			
		||||
 | 
			
		||||
        # Validate the following:
 | 
			
		||||
        # 1. Virtual Machine is accessible via SSH
 | 
			
		||||
        # 2. Virtual Machine is vGPU enabled (via SSH)
 | 
			
		||||
        # 3. listVirtualMachines returns accurate information
 | 
			
		||||
        """
 | 
			
		||||
        self.virtual_machine = VirtualMachine.create(
 | 
			
		||||
            self.apiclient,
 | 
			
		||||
            self.services["vgpu260q"],
 | 
			
		||||
            accountid=self.account.name,
 | 
			
		||||
            domainid=self.account.domainid,
 | 
			
		||||
            serviceofferingid=self.service_offering.id,
 | 
			
		||||
            mode=self.services['mode']
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id)
 | 
			
		||||
 | 
			
		||||
        self.debug(
 | 
			
		||||
            "Verify listVirtualMachines response for virtual machine: %s"\
 | 
			
		||||
            % self.virtual_machine.id
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            isinstance(list_vms, list),
 | 
			
		||||
            True,
 | 
			
		||||
            "List VM response was not a valid list"
 | 
			
		||||
        )
 | 
			
		||||
        self.assertNotEqual(
 | 
			
		||||
            len(list_vms),
 | 
			
		||||
            0,
 | 
			
		||||
            "List VM response was empty"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        vm = list_vms[0]
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            vm.id,
 | 
			
		||||
            self.virtual_machine.id,
 | 
			
		||||
            "Virtual Machine ids do not match"
 | 
			
		||||
        )
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            vm.name,
 | 
			
		||||
            self.virtual_machine.name,
 | 
			
		||||
            "Virtual Machine names do not match"
 | 
			
		||||
        )
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
            vm.state,
 | 
			
		||||
            "Running",
 | 
			
		||||
            msg="VM is not in Running state"
 | 
			
		||||
        )
 | 
			
		||||
        list_hosts = list_hosts(
 | 
			
		||||
               self.apiclient,
 | 
			
		||||
               id=vm.hostid
 | 
			
		||||
               )
 | 
			
		||||
        hostip = list_hosts[0].ipaddress
 | 
			
		||||
        try:
 | 
			
		||||
            sshClient = SshClient(host=hostip, port=22, user='root',passwd=self.services["host_password"])
 | 
			
		||||
            res = sshClient.execute("xe vgpu-list vm-name-label=%s params=type-uuid %s" % (
 | 
			
		||||
                                   vm.instancename
 | 
			
		||||
                                 ))
 | 
			
		||||
            self.debug("SSH result: %s" % res)
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            self.fail("SSH Access failed for %s: %s" % \
 | 
			
		||||
                      (hostip, e)
 | 
			
		||||
                      )
 | 
			
		||||
        result = str(res)
 | 
			
		||||
        self.assertEqual(
 | 
			
		||||
                    result.count("type-uuid"),
 | 
			
		||||
                    1,
 | 
			
		||||
                    "VM is vGPU enabled."
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        try:
 | 
			
		||||
            cleanup_resources(self.apiclient, self.cleanup)
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            self.debug("Warning! Exception in tearDown: %s" % e)
 | 
			
		||||
@ -1462,6 +1462,9 @@ class ServiceOffering:
 | 
			
		||||
        if "deploymentplanner" in services:
 | 
			
		||||
            cmd.deploymentplanner = services["deploymentplanner"]
 | 
			
		||||
 | 
			
		||||
        if "serviceofferingdetails" in services:
 | 
			
		||||
            cmd.serviceofferingdetails.append({services['serviceofferingdetails']})
 | 
			
		||||
 | 
			
		||||
        if "isvolatile" in services:
 | 
			
		||||
            cmd.isvolatile = services["isvolatile"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -361,6 +361,71 @@
 | 
			
		||||
                                        }
 | 
			
		||||
                                    },
 | 
			
		||||
 | 
			
		||||
                                    pciDevice: {
 | 
			
		||||
                                        label: 'GPU Type',
 | 
			
		||||
                                        select: function(args) {
 | 
			
		||||
                                            var items = [];
 | 
			
		||||
                                            items.push({
 | 
			
		||||
                                                id: '',
 | 
			
		||||
                                                description: ''
 | 
			
		||||
                                            });
 | 
			
		||||
                                            items.push({
 | 
			
		||||
                                                id: 'GPU_Passthrough',
 | 
			
		||||
                                                description: 'GPU-Passthrough'
 | 
			
		||||
                                            });
 | 
			
		||||
                                            items.push({
 | 
			
		||||
                                                id: 'VGPU',
 | 
			
		||||
                                                description: 'VGPU'
 | 
			
		||||
                                            });
 | 
			
		||||
                                            args.response.success({
 | 
			
		||||
                                                data: items
 | 
			
		||||
                                            });
 | 
			
		||||
                                            args.$select.change(function() {
 | 
			
		||||
                                                var $form = $(this).closest('form');
 | 
			
		||||
                                                var $fields = $form.find('.field');
 | 
			
		||||
                                                if (($(this).val() == "") || $(this).val() == "GPU-Passthrough") {
 | 
			
		||||
                                                  $form.find('[rel=vgpuType]').hide();
 | 
			
		||||
                                                } else if ($(this).val() == "VGPU") {
 | 
			
		||||
                                                  $form.find('[rel=vgpuType]').css('display', 'block');
 | 
			
		||||
                                                }
 | 
			
		||||
                                            });
 | 
			
		||||
                                        }
 | 
			
		||||
                                    },
 | 
			
		||||
 | 
			
		||||
                                    vgpuType: {
 | 
			
		||||
                                        label: 'VGPU Type',
 | 
			
		||||
                                        select: function(args) {
 | 
			
		||||
                                            var items = [];
 | 
			
		||||
                                            items.push({
 | 
			
		||||
                                                id: '',
 | 
			
		||||
                                                description: ''
 | 
			
		||||
                                            });
 | 
			
		||||
                                            items.push({
 | 
			
		||||
                                                id: 'GRID K100',
 | 
			
		||||
                                                description: 'GRID K100'
 | 
			
		||||
                                            });
 | 
			
		||||
                                            items.push({
 | 
			
		||||
                                                id: 'GRID K140Q',
 | 
			
		||||
                                                description: 'GRID K140Q'
 | 
			
		||||
                                            });
 | 
			
		||||
                                            items.push({
 | 
			
		||||
                                                id: 'GRID K200',
 | 
			
		||||
                                                description: 'GRID K200'
 | 
			
		||||
                                            });
 | 
			
		||||
                                            items.push({
 | 
			
		||||
                                                id: 'GRID K240Q',
 | 
			
		||||
                                                description: 'GRID K240Q'
 | 
			
		||||
                                            });
 | 
			
		||||
                                            items.push({
 | 
			
		||||
                                                id: 'GRID K260Q',
 | 
			
		||||
                                                description: 'GRID K260Q'
 | 
			
		||||
                                            });
 | 
			
		||||
                                            args.response.success({
 | 
			
		||||
                                                data: items
 | 
			
		||||
                                            });
 | 
			
		||||
                                        }
 | 
			
		||||
                                    },
 | 
			
		||||
 | 
			
		||||
                                    domainId: {
 | 
			
		||||
                                        label: 'label.domain',
 | 
			
		||||
                                        docID: 'helpComputeOfferingDomain',
 | 
			
		||||
@ -428,6 +493,14 @@
 | 
			
		||||
                                    array1.push("&serviceofferingdetails[0].ImplicitDedicationMode" + "=" + args.data.plannerMode);
 | 
			
		||||
                                }
 | 
			
		||||
 | 
			
		||||
                                if (args.data.pciDevice != "") {
 | 
			
		||||
                                    array1.push("&serviceofferingdetails[1].pciDevice" + "=" + args.data.pciDevice);
 | 
			
		||||
                                }
 | 
			
		||||
 | 
			
		||||
                                if (args.data.pciDevice == "VGPU") {
 | 
			
		||||
                                    array1.push("&serviceofferingdetails[2].vgpuType" + "=" + args.data.vgpuType);
 | 
			
		||||
                                }
 | 
			
		||||
 | 
			
		||||
                                if (args.data.networkRate != null && args.data.networkRate.length > 0) {
 | 
			
		||||
                                    $.extend(data, {
 | 
			
		||||
                                        networkrate: args.data.networkRate
 | 
			
		||||
 | 
			
		||||
@ -1804,7 +1804,9 @@
 | 
			
		||||
                            memory: {
 | 
			
		||||
                            	label: 'label.memory.mb'
 | 
			
		||||
                            },
 | 
			
		||||
                            
 | 
			
		||||
                            vgpu: {
 | 
			
		||||
                                label: 'VGPU'
 | 
			
		||||
                            },
 | 
			
		||||
                            haenable: {
 | 
			
		||||
                                label: 'label.ha.enabled',
 | 
			
		||||
                                converter: cloudStack.converters.toBooleanText
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user