mirror of https://github.com/apache/cloudstack.git
Merge branch 'master' into resize-root
This commit is contained in:
commit
dd4f6bfacf
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -483,6 +483,7 @@ public class EventTypes {
|
|||
|
||||
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
|
||||
// current ActionEvent annotation semantics
|
||||
// TODO #2 - The map should be from event type to class.
|
||||
|
||||
entityEventDetails = new HashMap<String, String>();
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1441,7 +1441,7 @@ label.group.by.zone=group by zone
|
|||
label.group.by.pod=group by pod
|
||||
label.group.by.cluster=group by cluster
|
||||
label.group.by.account=group by account
|
||||
label.no.grouping=(no grouping)\
|
||||
label.no.grouping=(no grouping)
|
||||
label.create.nfs.secondary.staging.storage=Create NFS Secondary Staging Store
|
||||
label.username.lower=username
|
||||
label.password.lower=password
|
||||
|
|
|
|||
|
|
@ -1440,7 +1440,7 @@ label.group.by.zone=\u30be\u30fc\u30f3\u5225\u30b0\u30eb\u30fc\u30d7
|
|||
label.group.by.pod=\u30dd\u30c3\u30c9\u5225\u30b0\u30eb\u30fc\u30d7
|
||||
label.group.by.cluster=\u30af\u30e9\u30b9\u30bf\u30fc\u5225\u30b0\u30eb\u30fc\u30d7
|
||||
label.group.by.account=\u30a2\u30ab\u30a6\u30f3\u30c8\u5225\u30b0\u30eb\u30fc\u30d7
|
||||
label.no.grouping=(\u30b0\u30eb\u30fc\u30d7\u306a\u3057)\
|
||||
label.no.grouping=(\u30b0\u30eb\u30fc\u30d7\u306a\u3057)
|
||||
label.create.nfs.secondary.staging.storage=NFS \u30bb\u30ab\u30f3\u30c0\u30ea \u30b9\u30c6\u30fc\u30b8\u30f3\u30b0 \u30b9\u30c8\u30a2\u3092\u4f5c\u6210\u3059\u308b
|
||||
label.username.lower=\u30e6\u30fc\u30b6\u30fc\u540d
|
||||
label.password.lower=\u30d1\u30b9\u30ef\u30fc\u30c9
|
||||
|
|
|
|||
|
|
@ -1440,7 +1440,7 @@ label.group.by.zone=\u6309\u8d44\u6e90\u57df\u5206\u7ec4
|
|||
label.group.by.pod=\u6309\u63d0\u4f9b\u70b9\u5206\u7ec4
|
||||
label.group.by.cluster=\u6309\u7fa4\u96c6\u5206\u7ec4
|
||||
label.group.by.account=\u6309\u5e10\u6237\u5206\u7ec4
|
||||
label.no.grouping=(\u4e0d\u5206\u7ec4)\
|
||||
label.no.grouping=(\u4e0d\u5206\u7ec4)
|
||||
label.create.nfs.secondary.staging.storage=\u521b\u5efa NFS \u4e8c\u7ea7\u6682\u5b58\u5b58\u50a8
|
||||
label.username.lower=\u7528\u6237\u540d
|
||||
label.password.lower=\u5bc6\u7801
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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" />
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public class HypervGuru extends HypervisorGuruBase implements HypervisorGuru {
|
|||
@Inject HypervManager _hypervMgr;
|
||||
@Inject NetworkDao _networkDao;
|
||||
@Inject NetworkModel _networkMgr;
|
||||
|
||||
int MaxNicSupported = 8;
|
||||
@Override
|
||||
public final HypervisorType getHypervisorType() {
|
||||
return HypervisorType.Hyperv;
|
||||
|
|
@ -85,7 +85,7 @@ public class HypervGuru extends HypervisorGuruBase implements HypervisorGuru {
|
|||
NicTO[] nics = to.getNics();
|
||||
|
||||
// reserve extra NICs
|
||||
NicTO[] expandedNics = new NicTO[nics.length + _hypervMgr.getRouterExtraPublicNics()];
|
||||
NicTO[] expandedNics = new NicTO[MaxNicSupported];
|
||||
int i = 0;
|
||||
int deviceId = -1;
|
||||
for(i = 0; i < nics.length; i++) {
|
||||
|
|
@ -97,8 +97,9 @@ public class HypervGuru extends HypervisorGuruBase implements HypervisorGuru {
|
|||
|
||||
long networkId = publicNicProfile.getNetworkId();
|
||||
NetworkVO network = _networkDao.findById(networkId);
|
||||
|
||||
for(; i < nics.length + _hypervMgr.getRouterExtraPublicNics(); i++) {
|
||||
// for Hyperv Hot Nic plug is not supported and it will support upto 8 nics.
|
||||
// creating the VR with extra nics (actual nics(3) + extra nics) will be 8
|
||||
for(; i < MaxNicSupported; i++) {
|
||||
NicTO nicTo = new NicTO();
|
||||
nicTo.setDeviceId(deviceId++);
|
||||
nicTo.setBroadcastType(publicNicProfile.getBroadcastType());
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ import com.cloud.agent.api.NetworkUsageCommand;
|
|||
import com.cloud.agent.api.PingCommand;
|
||||
import com.cloud.agent.api.PingRoutingCommand;
|
||||
import com.cloud.agent.api.PingTestCommand;
|
||||
import com.cloud.agent.api.SetupGuestNetworkCommand;
|
||||
import com.cloud.agent.api.StartCommand;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.StartupRoutingCommand;
|
||||
|
|
@ -98,6 +99,7 @@ import com.cloud.agent.api.routing.DnsMasqConfigCommand;
|
|||
import com.cloud.agent.api.routing.IpAliasTO;
|
||||
import com.cloud.agent.api.routing.IpAssocAnswer;
|
||||
import com.cloud.agent.api.routing.IpAssocCommand;
|
||||
import com.cloud.agent.api.routing.IpAssocVpcCommand;
|
||||
import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
|
||||
import com.cloud.agent.api.routing.NetworkElementCommand;
|
||||
import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand;
|
||||
|
|
@ -105,6 +107,7 @@ import com.cloud.agent.api.routing.SavePasswordCommand;
|
|||
import com.cloud.agent.api.routing.SetFirewallRulesAnswer;
|
||||
import com.cloud.agent.api.routing.SetFirewallRulesCommand;
|
||||
import com.cloud.agent.api.routing.SetMonitorServiceCommand;
|
||||
import com.cloud.agent.api.routing.SetNetworkACLCommand;
|
||||
import com.cloud.agent.api.routing.SetPortForwardingRulesAnswer;
|
||||
import com.cloud.agent.api.routing.SetPortForwardingRulesCommand;
|
||||
import com.cloud.agent.api.routing.SetSourceNatAnswer;
|
||||
|
|
@ -119,9 +122,12 @@ import com.cloud.agent.api.routing.VpnUsersCfgCommand;
|
|||
import com.cloud.agent.api.to.DhcpTO;
|
||||
import com.cloud.agent.api.to.FirewallRuleTO;
|
||||
import com.cloud.agent.api.to.IpAddressTO;
|
||||
import com.cloud.agent.api.to.NicTO;
|
||||
import com.cloud.agent.api.to.PortForwardingRuleTO;
|
||||
import com.cloud.agent.api.to.StaticNatRuleTO;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.agent.resource.virtualnetwork.VirtualRouterDeployer;
|
||||
import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource;
|
||||
import com.cloud.dc.DataCenter.NetworkType;
|
||||
import com.cloud.exception.InternalErrorException;
|
||||
import com.cloud.host.Host.Type;
|
||||
|
|
@ -135,6 +141,7 @@ import com.cloud.network.rules.FirewallRule;
|
|||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.resource.ServerResourceBase;
|
||||
import com.cloud.serializer.GsonHelper;
|
||||
import com.cloud.utils.ExecutionResult;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
|
|
@ -148,7 +155,7 @@ import com.cloud.vm.VirtualMachineName;
|
|||
* Implementation of dummy resource to be returned from discoverer.
|
||||
**/
|
||||
@Local(value = ServerResource.class)
|
||||
public class HypervDirectConnectResource extends ServerResourceBase implements ServerResource {
|
||||
public class HypervDirectConnectResource extends ServerResourceBase implements ServerResource, VirtualRouterDeployer {
|
||||
public static final int DEFAULT_AGENT_PORT = 8250;
|
||||
public static final String HOST_VM_STATE_REPORT_COMMAND = "org.apache.cloudstack.HostVmStateReportCommand";
|
||||
private static final Logger s_logger = Logger.getLogger(HypervDirectConnectResource.class.getName());
|
||||
|
|
@ -178,6 +185,7 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
|
|||
private static HypervManager s_hypervMgr;
|
||||
@Inject
|
||||
HypervManager _hypervMgr;
|
||||
protected VirtualRoutingResource _vrResource;
|
||||
|
||||
@PostConstruct
|
||||
void init() {
|
||||
|
|
@ -421,8 +429,9 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
|
|||
s_logger.error(errMsg, e);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (clazz == CheckSshCommand.class) {
|
||||
if (cmd instanceof NetworkElementCommand) {
|
||||
return _vrResource.executeRequest((NetworkElementCommand)cmd);
|
||||
}if (clazz == CheckSshCommand.class) {
|
||||
answer = execute((CheckSshCommand)cmd);
|
||||
} else if (clazz == GetDomRVersionCmd.class) {
|
||||
answer = execute((GetDomRVersionCmd)cmd);
|
||||
|
|
@ -499,6 +508,203 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
|
|||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutionResult executeInVR(String routerIP, String script, String args) {
|
||||
Pair<Boolean, String> result;
|
||||
|
||||
//TODO: Password should be masked, cannot output to log directly
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Run command on VR: " + routerIP + ", script: " + script + " with args: " + args);
|
||||
}
|
||||
|
||||
try {
|
||||
result = SshHelper.sshExecute(routerIP, DEFAULT_DOMR_SSHPORT, "root", getSystemVMKeyFile(), null, "/opt/cloud/bin/" + script + " " + args);
|
||||
} catch (Exception e) {
|
||||
String msg = "Command failed due to " + e ;
|
||||
s_logger.error(msg);
|
||||
result = new Pair<Boolean, String>(false, msg);
|
||||
}
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug(script + " execution result: " + result.first().toString());
|
||||
}
|
||||
return new ExecutionResult(result.first(), result.second());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutionResult createFileInVR(String routerIp, String filePath, String fileName, String content) {
|
||||
File keyFile = getSystemVMKeyFile();
|
||||
try {
|
||||
SshHelper.scpTo(routerIp, 3922, "root", keyFile, null, filePath, content.getBytes(), fileName, null);
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("Fail to create file " + filePath + fileName + " in VR " + routerIp, e);
|
||||
return new ExecutionResult(false, e.getMessage());
|
||||
}
|
||||
return new ExecutionResult(true, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutionResult prepareCommand(NetworkElementCommand cmd) {
|
||||
//Update IP used to access router
|
||||
cmd.setRouterAccessIp(getRouterSshControlIp(cmd));
|
||||
assert cmd.getRouterAccessIp() != null;
|
||||
|
||||
if (cmd instanceof IpAssocVpcCommand) {
|
||||
return prepareNetworkElementCommand((IpAssocVpcCommand)cmd);
|
||||
} else if (cmd instanceof IpAssocCommand) {
|
||||
return prepareNetworkElementCommand((IpAssocCommand)cmd);
|
||||
} else if (cmd instanceof SetSourceNatCommand) {
|
||||
return prepareNetworkElementCommand((SetSourceNatCommand)cmd);
|
||||
} else if (cmd instanceof SetupGuestNetworkCommand) {
|
||||
return prepareNetworkElementCommand((SetupGuestNetworkCommand)cmd);
|
||||
} else if (cmd instanceof SetNetworkACLCommand) {
|
||||
return prepareNetworkElementCommand((SetNetworkACLCommand)cmd);
|
||||
}
|
||||
return new ExecutionResult(true, null);
|
||||
}
|
||||
|
||||
private ExecutionResult prepareNetworkElementCommand(IpAssocCommand cmd) {
|
||||
try {
|
||||
|
||||
IpAddressTO[] ips = cmd.getIpAddresses();
|
||||
String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
|
||||
String controlIp = getRouterSshControlIp(cmd);
|
||||
|
||||
for (IpAddressTO ip : ips) {
|
||||
/**
|
||||
* TODO support other networks
|
||||
*/
|
||||
URI broadcastUri = BroadcastDomainType.fromString(ip.getBroadcastUri());
|
||||
if (BroadcastDomainType.getSchemeValue(broadcastUri) != BroadcastDomainType.Vlan) {
|
||||
throw new InternalErrorException("Unable to assign a public IP to a VIF on network " + ip.getBroadcastUri());
|
||||
}
|
||||
int vlanId = Integer.parseInt(BroadcastDomainType.getValue(broadcastUri));
|
||||
int publicNicInfo = -1;
|
||||
publicNicInfo = getVmNics(routerName, vlanId);
|
||||
|
||||
boolean addVif = false;
|
||||
if (ip.isAdd() && publicNicInfo == -1) {
|
||||
if (s_logger.isDebugEnabled()) {
|
||||
s_logger.debug("Plug new NIC to associate" + controlIp + " to " + ip.getPublicIp());
|
||||
}
|
||||
addVif = true;
|
||||
}
|
||||
|
||||
if (addVif) {
|
||||
Pair<Integer, String> nicdevice = findRouterFreeEthDeviceIndex(controlIp);
|
||||
publicNicInfo = nicdevice.first();
|
||||
if (publicNicInfo > 0) {
|
||||
modifyNicVlan(routerName, vlanId, nicdevice.second());
|
||||
// After modifying the vnic on VR, check the VR VNics config in the host and get the device position
|
||||
publicNicInfo = getVmNics(routerName, vlanId);
|
||||
// As a new nic got activated in the VR. add the entry in the NIC's table.
|
||||
networkUsage(controlIp, "addVif", "eth" + publicNicInfo);
|
||||
}
|
||||
else {
|
||||
// we didn't find any eth device available in VR to configure the ip range with new VLAN
|
||||
String msg = "No Nic is available on DomR VIF to associate/disassociate IP with.";
|
||||
s_logger.error(msg);
|
||||
throw new InternalErrorException(msg);
|
||||
}
|
||||
ip.setNicDevId(publicNicInfo);
|
||||
ip.setNewNic(addVif);
|
||||
} else {
|
||||
ip.setNicDevId(publicNicInfo);
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
s_logger.error("Unexpected exception: " + e.toString() + " will shortcut rest of IPAssoc commands", e);
|
||||
return new ExecutionResult(false, e.toString());
|
||||
}
|
||||
return new ExecutionResult(true, null);
|
||||
}
|
||||
|
||||
protected ExecutionResult prepareNetworkElementCommand(SetupGuestNetworkCommand cmd) {
|
||||
NicTO nic = cmd.getNic();
|
||||
String routerIp = getRouterSshControlIp(cmd);
|
||||
String domrName =
|
||||
cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
|
||||
|
||||
try {
|
||||
int ethDeviceNum = findRouterEthDeviceIndex(domrName, routerIp,
|
||||
nic.getMac());
|
||||
nic.setDeviceId(ethDeviceNum);
|
||||
} catch (Exception e) {
|
||||
String msg = "Prepare SetupGuestNetwork failed due to " + e.toString();
|
||||
s_logger.warn(msg, e);
|
||||
return new ExecutionResult(false, msg);
|
||||
}
|
||||
return new ExecutionResult(true, null);
|
||||
}
|
||||
|
||||
|
||||
private ExecutionResult prepareNetworkElementCommand(IpAssocVpcCommand cmd) {
|
||||
String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
|
||||
String routerIp = getRouterSshControlIp(cmd);
|
||||
|
||||
try {
|
||||
IpAddressTO[] ips = cmd.getIpAddresses();
|
||||
for (IpAddressTO ip : ips) {
|
||||
|
||||
int ethDeviceNum = findRouterEthDeviceIndex(routerName, routerIp, ip.getVifMacAddress());
|
||||
if (ethDeviceNum < 0) {
|
||||
if (ip.isAdd()) {
|
||||
throw new InternalErrorException("Failed to find DomR VIF to associate/disassociate IP with.");
|
||||
} else {
|
||||
s_logger.debug("VIF to deassociate IP with does not exist, return success");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ip.setNicDevId(ethDeviceNum);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.error("Prepare Ip Assoc failure on applying one ip due to exception: ", e);
|
||||
return new ExecutionResult(false, e.toString());
|
||||
}
|
||||
|
||||
return new ExecutionResult(true, null);
|
||||
}
|
||||
|
||||
protected ExecutionResult prepareNetworkElementCommand(SetSourceNatCommand cmd) {
|
||||
String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
|
||||
String routerIp = getRouterSshControlIp(cmd);
|
||||
IpAddressTO pubIp = cmd.getIpAddress();
|
||||
|
||||
try {
|
||||
int ethDeviceNum = findRouterEthDeviceIndex(routerName, routerIp, pubIp.getVifMacAddress());
|
||||
pubIp.setNicDevId(ethDeviceNum);
|
||||
} catch (Exception e) {
|
||||
String msg = "Prepare Ip SNAT failure due to " + e.toString();
|
||||
s_logger.error(msg, e);
|
||||
return new ExecutionResult(false, e.toString());
|
||||
}
|
||||
return new ExecutionResult(true, null);
|
||||
}
|
||||
|
||||
private ExecutionResult prepareNetworkElementCommand(SetNetworkACLCommand cmd) {
|
||||
NicTO nic = cmd.getNic();
|
||||
String routerName =
|
||||
cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
|
||||
String routerIp = getRouterSshControlIp(cmd);
|
||||
|
||||
try {
|
||||
int ethDeviceNum = findRouterEthDeviceIndex(routerName, routerIp,
|
||||
nic.getMac());
|
||||
nic.setDeviceId(ethDeviceNum);
|
||||
} catch (Exception e) {
|
||||
String msg = "Prepare SetNetworkACL failed due to " + e.toString();
|
||||
s_logger.error(msg, e);
|
||||
return new ExecutionResult(false, msg);
|
||||
}
|
||||
return new ExecutionResult(true, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExecutionResult cleanupCommand(NetworkElementCommand cmd) {
|
||||
return new ExecutionResult(true, null);
|
||||
}
|
||||
|
||||
protected Answer execute(final RemoteAccessVpnCfgCommand cmd) {
|
||||
String controlIp = getRouterSshControlIp(cmd);
|
||||
StringBuffer argsBuf = new StringBuffer();
|
||||
|
|
@ -1926,6 +2132,10 @@ public class HypervDirectConnectResource extends ServerResourceBase implements S
|
|||
_configureCalled = true;
|
||||
}
|
||||
|
||||
_vrResource = new VirtualRoutingResource(this);
|
||||
if (!_vrResource.configure(name, new HashMap<String, Object>())) {
|
||||
throw new ConfigurationException("Unable to configure VirtualRoutingResource");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4390,6 +4390,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
try {
|
||||
conn = LibvirtConnection.getConnectionByType(HypervisorType.LXC.toString());
|
||||
vmStates.putAll(getAllVms(conn));
|
||||
conn = LibvirtConnection.getConnectionByType(HypervisorType.KVM.toString());
|
||||
vmStates.putAll(getAllVms(conn));
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.debug("Failed to get connection: " + e.getMessage());
|
||||
}
|
||||
|
|
@ -4486,6 +4488,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||
try {
|
||||
conn = LibvirtConnection.getConnectionByType(HypervisorType.LXC.toString());
|
||||
vmStates.putAll(getHostVmStateReport(conn));
|
||||
conn = LibvirtConnection.getConnectionByType(HypervisorType.KVM.toString());
|
||||
vmStates.putAll(getHostVmStateReport(conn));
|
||||
} catch (LibvirtException e) {
|
||||
s_logger.debug("Failed to get connection: " + e.getMessage());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ public class CiscoNexusVSMElement extends CiscoNexusVSMDeviceManagerImpl impleme
|
|||
ClusterDao _clusterDao;
|
||||
@Inject
|
||||
ClusterVSMMapDao _clusterVSMDao;
|
||||
@Inject
|
||||
ManagementService _mgr;
|
||||
|
||||
@Override
|
||||
public Map<Service, Map<Capability, String>> getCapabilities() {
|
||||
|
|
@ -190,7 +192,8 @@ public class CiscoNexusVSMElement extends CiscoNexusVSMDeviceManagerImpl impleme
|
|||
// Else if there is only a zoneId defined, get a list of all vmware clusters
|
||||
// in the zone, and then for each cluster, pull the VSM and prepare a list.
|
||||
if (zoneId != null && zoneId.longValue() != 0) {
|
||||
ManagementService ref = cmd.getMgmtServiceRef();
|
||||
ManagementService ref = _mgr;
|
||||
;
|
||||
List<? extends Cluster> clusterList = ref.searchForClusters(zoneId, cmd.getStartIndex(), cmd.getPageSizeVal(), "VMware");
|
||||
|
||||
if (clusterList.size() == 0) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ import javax.annotation.PostConstruct;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.utils.ReflectUtil;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseAsyncCmd;
|
||||
import org.apache.cloudstack.api.BaseAsyncCreateCmd;
|
||||
|
|
@ -83,13 +85,18 @@ public class ApiDispatcher {
|
|||
|
||||
final BaseAsyncCmd asyncCmd = (BaseAsyncCmd)cmd;
|
||||
final String startEventId = params.get(ApiConstants.CTX_START_EVENT_ID);
|
||||
String uuid = params.get("uuid");
|
||||
String uuid = params.get(ApiConstants.UUID);
|
||||
ctx.setStartEventId(Long.valueOf(startEventId));
|
||||
|
||||
// Fow now use the key from EventTypes.java rather than getInstanceType bcz the later doesn't refer to the interfaces
|
||||
// Add the resource id in the call context, also add some other first class object ids (for now vm) if available.
|
||||
// TODO - this should be done for all the uuids passed in the cmd - so should be moved where uuid to id conversion happens.
|
||||
if(EventTypes.getEntityForEvent(asyncCmd.getEventType()) != null){
|
||||
ctx.putContextParameter(EventTypes.getEntityForEvent(asyncCmd.getEventType()), uuid);
|
||||
}
|
||||
if(params.get(ApiConstants.VIRTUAL_MACHINE_ID) != null){
|
||||
ctx.putContextParameter(ReflectUtil.getEntityName(VirtualMachine.class), params.get(ApiConstants.VIRTUAL_MACHINE_ID));
|
||||
}
|
||||
|
||||
// Synchronise job on the object if needed
|
||||
if (asyncCmd.getJob() != null && asyncCmd.getSyncObjId() != null && asyncCmd.getSyncObjType() != null) {
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ import javax.servlet.http.HttpServletResponse;
|
|||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import com.cloud.event.EventTypes;
|
||||
import com.cloud.utils.ReflectUtil;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import org.apache.cloudstack.acl.APIChecker;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
|
|
@ -503,6 +505,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
|
|||
final CallContext ctx = CallContext.current();
|
||||
final Long callerUserId = ctx.getCallingUserId();
|
||||
final Account caller = ctx.getCallingAccount();
|
||||
String vmUUID = params.get(ApiConstants.VIRTUAL_MACHINE_ID);
|
||||
|
||||
// Queue command based on Cmd super class:
|
||||
// BaseCmd: cmd is dispatched to ApiDispatcher, executed, serialized and returned.
|
||||
|
|
@ -519,7 +522,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
|
|||
params.put("id", objectId.toString());
|
||||
} else {
|
||||
// Extract the uuid before params are processed and id reflects internal db id
|
||||
objectUuid = params.get("id");
|
||||
objectUuid = params.get(ApiConstants.ID);
|
||||
dispatchChainFactory.getStandardDispatchChain().dispatch(new DispatchTask(cmdObj, params));
|
||||
}
|
||||
|
||||
|
|
@ -538,9 +541,15 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer
|
|||
long startEventId = ctx.getStartEventId();
|
||||
asyncCmd.setStartEventId(startEventId);
|
||||
|
||||
// Add the resource id in the call context, also add some other first class object ids (for now vm) if available.
|
||||
// TODO - this should be done for all the uuids passed in the cmd - so should be moved where uuid to id conversion happens.
|
||||
if(EventTypes.getEntityForEvent(asyncCmd.getEventType()) != null){
|
||||
ctx.putContextParameter(EventTypes.getEntityForEvent(asyncCmd.getEventType()), objectUuid);
|
||||
}
|
||||
if(vmUUID != null){
|
||||
ctx.putContextParameter(ReflectUtil.getEntityName(VirtualMachine.class), vmUUID);
|
||||
}
|
||||
|
||||
// save the scheduled event
|
||||
final Long eventId =
|
||||
ActionEventUtils.onScheduledActionEvent((callerUserId == null) ? User.UID_SYSTEM : callerUserId, asyncCmd.getEntityOwnerId(), asyncCmd.getEventType(),
|
||||
|
|
|
|||
|
|
@ -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,6 +25,8 @@ import java.util.Map;
|
|||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.utils.ReflectUtil;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
|
||||
|
|
@ -186,10 +188,12 @@ public class ActionEventUtils {
|
|||
String entityType = null;
|
||||
String entityUuid = null;
|
||||
CallContext context = CallContext.current();
|
||||
String vmEntityName = ReflectUtil.getEntityName(VirtualMachine.class);
|
||||
String vmuuid = (String) context.getContextParameter(vmEntityName);
|
||||
Class entityKey = getEntityKey(eventType);
|
||||
if (entityKey != null)
|
||||
{
|
||||
//FIXME - Remove this
|
||||
//FIXME - Remove this since it should be covered by the else if condition below.
|
||||
entityUuid = (String)context.getContextParameter(entityKey);
|
||||
if (entityUuid != null)
|
||||
entityType = entityKey.getName();
|
||||
|
|
@ -220,6 +224,8 @@ public class ActionEventUtils {
|
|||
eventDescription.put("status", state.toString());
|
||||
eventDescription.put("entity", entityType);
|
||||
eventDescription.put("entityuuid", entityUuid);
|
||||
//Put all the first class entities that are touched during the action. For now atleast put in the vmid.
|
||||
eventDescription.put(vmEntityName, vmuuid);
|
||||
eventDescription.put("description", description);
|
||||
|
||||
String eventDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").format(new Date());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -2179,6 +2179,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
hTypes.add(HypervisorType.VMware);
|
||||
hTypes.add(HypervisorType.KVM);
|
||||
hTypes.add(HypervisorType.Simulator);
|
||||
hTypes.add(HypervisorType.LXC);
|
||||
return hTypes;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -1471,6 +1475,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;
|
||||
|
|
@ -3873,6 +3874,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)) {
|
||||
|
|
@ -4184,6 +4190,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;
|
||||
|
||||
|
|
|
|||
|
|
@ -1221,10 +1221,6 @@ start() {
|
|||
patch_log4j
|
||||
parse_cmd_line
|
||||
change_password
|
||||
if [ "$hyp" == "hyperv" ]; then
|
||||
# eject the systemvm.iso
|
||||
eject
|
||||
fi
|
||||
case $TYPE in
|
||||
router)
|
||||
[ "$NAME" == "" ] && NAME=router
|
||||
|
|
@ -1259,6 +1255,10 @@ start() {
|
|||
setup_default;
|
||||
;;
|
||||
esac
|
||||
if [ "$hyp" == "hyperv" ]; then
|
||||
# eject the systemvm.iso
|
||||
eject
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -51,8 +51,7 @@ class configuration(object):
|
|||
class logger(object):
|
||||
def __init__(self):
|
||||
'''TestCase/TestClient'''
|
||||
self.name = None
|
||||
self.file = None
|
||||
self.logFolderPath = None
|
||||
|
||||
|
||||
class cloudstackConfiguration(object):
|
||||
|
|
@ -61,7 +60,7 @@ class cloudstackConfiguration(object):
|
|||
self.mgtSvr = []
|
||||
self.dbSvr = None
|
||||
self.globalConfig = []
|
||||
self.logger = []
|
||||
self.logger = None
|
||||
|
||||
|
||||
class zone(object):
|
||||
|
|
|
|||
|
|
@ -1465,6 +1465,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"]
|
||||
|
||||
|
|
|
|||
|
|
@ -54,22 +54,22 @@ def describeResources(config):
|
|||
lbprovider = provider()
|
||||
lbprovider.name = 'InternalLbVm'
|
||||
|
||||
pn = physical_network()
|
||||
pn = physicalNetwork()
|
||||
pn.name = "Sandbox-pnet"
|
||||
pn.vlan = config.get('cloudstack', 'pnet.vlan')
|
||||
pn.tags = ["cloud-simulator-public"]
|
||||
pn.traffictypes = [traffictype("Guest"),
|
||||
traffictype("Management", {"simulator" : "cloud-simulator-mgmt"}),
|
||||
traffictype("Public", {"simulator":"cloud-simulator-public"})]
|
||||
pn.traffictypes = [trafficType("Guest"),
|
||||
trafficType("Management", {"simulator" : "cloud-simulator-mgmt"}),
|
||||
trafficType("Public", {"simulator":"cloud-simulator-public"})]
|
||||
pn.isolationmethods = ["VLAN"]
|
||||
pn.providers.append(vpcprovider)
|
||||
pn.providers.append(lbprovider)
|
||||
|
||||
pn2 = physical_network()
|
||||
pn2 = physicalNetwork()
|
||||
pn2.name = "Sandbox-pnet2"
|
||||
pn2.vlan = config.get('cloudstack', 'pnet2.vlan')
|
||||
pn2.tags = ["cloud-simulator-guest"]
|
||||
pn2.traffictypes = [traffictype('Guest', {'simulator': 'cloud-simulator-guest'})]
|
||||
pn2.traffictypes = [trafficType('Guest', {'simulator': 'cloud-simulator-guest'})]
|
||||
pn2.isolationmethods = ["VLAN"]
|
||||
pn2.providers.append(vpcprovider)
|
||||
pn2.providers.append(lbprovider)
|
||||
|
|
@ -137,16 +137,11 @@ def describeResources(config):
|
|||
[zs.globalConfig.append(cfg) for cfg in getGlobalSettings(config)]
|
||||
|
||||
''''add loggers'''
|
||||
testClientLogger = logger()
|
||||
testClientLogger.name = 'TestClient'
|
||||
testClientLogger.file = 'testclient.log'
|
||||
testLogger = logger()
|
||||
testLogger.logFolderPath = '/tmp/'
|
||||
zs.logger = testLogger
|
||||
|
||||
testCaseLogger = logger()
|
||||
testCaseLogger.name = 'TestCase'
|
||||
testCaseLogger.file = 'testcase.log'
|
||||
|
||||
zs.logger.append(testClientLogger)
|
||||
zs.logger.append(testCaseLogger)
|
||||
return zs
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -51,11 +51,11 @@ def describeResources(config):
|
|||
sgprovider.broadcastdomainrange = 'ZONE'
|
||||
sgprovider.name = 'SecurityGroupProvider'
|
||||
|
||||
pn = physical_network()
|
||||
pn = physicalNetwork()
|
||||
pn.name = "Sandbox-pnet"
|
||||
pn.tags = ["cloud-simulator-pnet"]
|
||||
pn.traffictypes = [traffictype("Guest"),
|
||||
traffictype("Management", {"simulator" : "cloud-simulator-mgmt"})]
|
||||
pn.traffictypes = [trafficType("Guest"),
|
||||
trafficType("Management", {"simulator" : "cloud-simulator-mgmt"})]
|
||||
pn.isolationmethods = ["VLAN"]
|
||||
pn.providers.append(sgprovider)
|
||||
|
||||
|
|
@ -121,16 +121,10 @@ def describeResources(config):
|
|||
[zs.globalConfig.append(cfg) for cfg in getGlobalSettings(config)]
|
||||
|
||||
''''add loggers'''
|
||||
testClientLogger = logger()
|
||||
testClientLogger.name = 'TestClient'
|
||||
testClientLogger.file = 'testclient.log'
|
||||
testLogger = logger()
|
||||
testLogger.logFolderPath = '/tmp/'
|
||||
zs.logger = testLogger
|
||||
|
||||
testCaseLogger = logger()
|
||||
testCaseLogger.name = 'TestCase'
|
||||
testCaseLogger.file = 'testcase.log'
|
||||
|
||||
zs.logger.append(testClientLogger)
|
||||
zs.logger.append(testCaseLogger)
|
||||
return zs
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -52,9 +52,9 @@ def describeResources(config):
|
|||
sgprovider.broadcastdomainrange = 'Pod'
|
||||
sgprovider.name = 'SecurityGroupProvider'
|
||||
|
||||
pn = physical_network()
|
||||
pn = physicalNetwork()
|
||||
pn.name = "Sandbox-pnet"
|
||||
pn.traffictypes = [traffictype("Guest"), traffictype("Management")]
|
||||
pn.traffictypes = [trafficType("Guest"), trafficType("Management")]
|
||||
pn.isolationmethods = ["L3"]
|
||||
pn.providers.append(sgprovider)
|
||||
|
||||
|
|
@ -119,16 +119,10 @@ def describeResources(config):
|
|||
[zs.globalConfig.append(cfg) for cfg in getGlobalSettings(config)]
|
||||
|
||||
''''add loggers'''
|
||||
testClientLogger = logger()
|
||||
testClientLogger.name = 'TestClient'
|
||||
testClientLogger.file = '/var/log/testclient.log'
|
||||
testLogger = logger()
|
||||
testLogger.logFolderPath = '/tmp/'
|
||||
zs.logger = testLogger
|
||||
|
||||
testCaseLogger = logger()
|
||||
testCaseLogger.name = 'TestCase'
|
||||
testCaseLogger.file = '/var/log/testcase.log'
|
||||
|
||||
zs.logger.append(testClientLogger)
|
||||
zs.logger.append(testCaseLogger)
|
||||
return zs
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -46,9 +46,9 @@ def describeResources(config):
|
|||
vpcprovider = provider()
|
||||
vpcprovider.name = 'VpcVirtualRouter'
|
||||
|
||||
pn = physical_network()
|
||||
pn = physicalNetwork()
|
||||
pn.name = "Sandbox-pnet"
|
||||
pn.traffictypes = [traffictype("Guest"), traffictype("Management"), traffictype("Public")]
|
||||
pn.traffictypes = [trafficType("Guest"), trafficType("Management"), trafficType("Public")]
|
||||
pn.isolationmethods = ["VLAN"]
|
||||
pn.providers.append(vpcprovider)
|
||||
pn.vlan = config.get('cloudstack', 'zone.vlan')
|
||||
|
|
@ -120,16 +120,10 @@ def describeResources(config):
|
|||
[zs.globalConfig.append(cfg) for cfg in getGlobalSettings(config)]
|
||||
|
||||
''''add loggers'''
|
||||
testClientLogger = logger()
|
||||
testClientLogger.name = 'TestClient'
|
||||
testClientLogger.file = '/var/log/testclient.log'
|
||||
testLogger = logger()
|
||||
testLogger.logFolderPath = '/tmp/'
|
||||
zs.logger = testLogger
|
||||
|
||||
testCaseLogger = logger()
|
||||
testCaseLogger.name = 'TestCase'
|
||||
testCaseLogger.file = '/var/log/testcase.log'
|
||||
|
||||
zs.logger.append(testClientLogger)
|
||||
zs.logger.append(testCaseLogger)
|
||||
return zs
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -927,7 +927,7 @@
|
|||
response: {
|
||||
success: function(args) {
|
||||
$(args.data).each(function() {
|
||||
$('<option>').val(this.name).html(_s(this.description))
|
||||
$('<option>').val(this.name).html(_l(_s(this.description)))
|
||||
.appendTo($select);
|
||||
});
|
||||
_medit.refreshItemWidths($multi);
|
||||
|
|
|
|||
|
|
@ -189,4 +189,17 @@ public class ReflectUtil {
|
|||
|
||||
}
|
||||
|
||||
public static String getEntityName(Class clz){
|
||||
if(clz == null)
|
||||
return null;
|
||||
|
||||
String entityName = clz.getName();
|
||||
int index = entityName.lastIndexOf(".");
|
||||
if (index != -1) {
|
||||
return entityName.substring(index + 1);
|
||||
}else{
|
||||
return entityName;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue