Merge branch 'master' into resize-root

This commit is contained in:
Marcus Sorensen 2014-02-10 20:12:56 -07:00
commit dd4f6bfacf
67 changed files with 1972 additions and 91 deletions

View File

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

View File

@ -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;
}
}

View File

@ -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>();

View File

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

View File

@ -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;

View File

@ -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() {

View File

@ -0,0 +1,46 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.response;
import java.util.List;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import com.cloud.serializer.Param;
public class GpuResponse extends BaseResponse {
@SerializedName(ApiConstants.GPUGROUPNAME)
@Param(description = "GPU cards present in the host")
private String gpuGroupName;
@SerializedName(ApiConstants.VGPU)
@Param(description = "the list of enabled vGPUs", responseObject = VgpuResponse.class)
private List<VgpuResponse> vgpu;
public void setGpuGroupName(String gpuGroupName) {
this.gpuGroupName = gpuGroupName;
}
public void setVgpu(List<VgpuResponse> vgpu) {
this.vgpu = vgpu;
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -0,0 +1,52 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.response;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponse;
import com.cloud.serializer.Param;
public class VgpuResponse extends BaseResponse {
@SerializedName(ApiConstants.VGPUTYPE)
@Param(description = "Model Name of vGPU")
private String name;
@SerializedName(ApiConstants.REMAININGCAPACITY)
@Param(description = "No. of more VMs can be deployped with this vGPU type")
private Long capacity;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getCapacity() {
return capacity;
}
public void setCapacity(Long capacity) {
this.capacity = capacity;
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

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

View File

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

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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" />

View File

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

View File

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

View File

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

View File

@ -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);
}
}

View File

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

View File

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

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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());

View File

@ -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;
}

View File

@ -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());
}

View File

@ -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) {

View File

@ -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);

View File

@ -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());

View File

@ -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);
}

View File

@ -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) {

View File

@ -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(),

View File

@ -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());

View File

@ -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)) {

View File

@ -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());

View File

@ -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;
}
}
}

View File

@ -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());

View File

@ -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)

View File

@ -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);

View File

@ -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;
}

View File

@ -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)

View File

@ -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()) {

View File

@ -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);
}

View File

@ -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) {

View File

@ -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");

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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>

View File

@ -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;

View File

@ -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
}

View File

@ -0,0 +1,227 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#Test from the Marvin - Testing in Python wiki
#All tests inherit from cloudstackTestCase
from marvin.cloudstackTestCase import cloudstackTestCase
#Import Integration Libraries
#base - contains all resources as entities and defines create, delete, list operations on them
from marvin.integration.lib.base import Account, VirtualMachine, ServiceOffering
#utils - utility classes for common cleanup, external library wrappers etc
from marvin.integration.lib.utils import cleanup_resources
#common - commonly used methods for all tests are listed here
from marvin.integration.lib.common import get_zone, get_domain, get_template
from nose.plugins.attrib import attr
class Services:
"""Test VM Life Cycle Services
"""
def __init__(self):
self.services = {
"disk_offering":{
"displaytext": "Small",
"name": "Small",
"disksize": 1
},
"account": {
"email": "test@test.com",
"firstname": "Test",
"lastname": "User",
"username": "test",
# Random characters are appended in create account to
# ensure unique username generated each time
"password": "password",
},
"vgpu260q": # Create a virtual machine instance with vgpu type as 260q
{
"displayname": "testserver",
"username": "root", # VM creds for SSH
"password": "password",
"ssh_port": 22,
"hypervisor": 'XenServer',
"privateport": 22,
"publicport": 22,
"protocol": 'TCP',
},
"vgpu140q": # Create a virtual machine instance with vgpu type as 140q
{
"displayname": "testserver",
"username": "root",
"password": "password",
"ssh_port": 22,
"hypervisor": 'XenServer',
"privateport": 22,
"publicport": 22,
"protocol": 'TCP',
},
"service_offerings":
{
"vgpu260qwin":
{
"name": "Windows Instance with vGPU260Q",
"displaytext": "Windows Instance with vGPU260Q",
"cpunumber": 2,
"cpuspeed": 1600, # in MHz
"memory": 3072, # In MBs
},
"vgpu140qwin":
{
# Small service offering ID to for change VM
# service offering from medium to small
"name": "Windows Instance with vGPU140Q",
"displaytext": "Windows Instance with vGPU140Q",
"cpunumber": 2,
"cpuspeed": 1600,
"memory": 3072,
}
},
"diskdevice": ['/dev/vdc', '/dev/vdb', '/dev/hdb', '/dev/hdc', '/dev/xvdd', '/dev/cdrom', '/dev/sr0', '/dev/cdrom1' ],
# Disk device where ISO is attached to instance
"mount_dir": "/mnt/tmp",
"sleep": 60,
"timeout": 10,
#Migrate VM to hostid
"ostype": 'Windows 7 (32-bit)',
# CentOS 5.3 (64-bit)
}
class TestDeployvGPUenabledVM(cloudstackTestCase):
"""Test deploy a vGPU enabled VM into a user account
"""
def setUp(self):
self.services = Services().services
self.apiclient = self.testClient.getApiClient()
# Get Zone, Domain and Default Built-in template
self.domain = get_domain(self.apiclient, self.services)
self.zone = get_zone(self.apiclient, self.services)
self.services["mode"] = self.zone.networktype
# Before running this test, register a windows template with ostype as 'Windows 7 (32-bit)'
self.template = get_template(self.apiclient, self.zone.id, self.services["ostype"], templatetype='USER')
#create a user account
self.account = Account.create(
self.apiclient,
self.services["account"],
domainid=self.domain.id
)
self.services["vgpu260q"]["zoneid"] = self.zone.id
self.services["vgpu260q"]["template"] = self.template.id
self.services["vgpu140q"]["zoneid"] = self.zone.id
self.services["vgpu140q"]["template"] = self.template.id
#create a service offering
self.service_offering = ServiceOffering.create(
self.apiclient,
self.services["service_offerings"]["vgpu260qwin"],
serviceofferingdetails={'pciDevice': 'VGPU'}
)
#build cleanup list
self.cleanup = [
self.service_offering,
self.account
]
@attr(tags = ['advanced', 'simulator', 'basic', 'vgpu'])
def test_deploy_vgpu_enabled_vm(self):
"""Test Deploy Virtual Machine
# Validate the following:
# 1. Virtual Machine is accessible via SSH
# 2. Virtual Machine is vGPU enabled (via SSH)
# 3. listVirtualMachines returns accurate information
"""
self.virtual_machine = VirtualMachine.create(
self.apiclient,
self.services["vgpu260q"],
accountid=self.account.name,
domainid=self.account.domainid,
serviceofferingid=self.service_offering.id,
mode=self.services['mode']
)
list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id)
self.debug(
"Verify listVirtualMachines response for virtual machine: %s"\
% self.virtual_machine.id
)
self.assertEqual(
isinstance(list_vms, list),
True,
"List VM response was not a valid list"
)
self.assertNotEqual(
len(list_vms),
0,
"List VM response was empty"
)
vm = list_vms[0]
self.assertEqual(
vm.id,
self.virtual_machine.id,
"Virtual Machine ids do not match"
)
self.assertEqual(
vm.name,
self.virtual_machine.name,
"Virtual Machine names do not match"
)
self.assertEqual(
vm.state,
"Running",
msg="VM is not in Running state"
)
list_hosts = list_hosts(
self.apiclient,
id=vm.hostid
)
hostip = list_hosts[0].ipaddress
try:
sshClient = SshClient(host=hostip, port=22, user='root',passwd=self.services["host_password"])
res = sshClient.execute("xe vgpu-list vm-name-label=%s params=type-uuid %s" % (
vm.instancename
))
self.debug("SSH result: %s" % res)
except Exception as e:
self.fail("SSH Access failed for %s: %s" % \
(hostip, e)
)
result = str(res)
self.assertEqual(
result.count("type-uuid"),
1,
"VM is vGPU enabled."
)
def tearDown(self):
try:
cleanup_resources(self.apiclient, self.cleanup)
except Exception as e:
self.debug("Warning! Exception in tearDown: %s" % e)

View File

@ -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):

View File

@ -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"]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -1804,7 +1804,9 @@
memory: {
label: 'label.memory.mb'
},
vgpu: {
label: 'VGPU'
},
haenable: {
label: 'label.ha.enabled',
converter: cloudStack.converters.toBooleanText

View File

@ -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);

View File

@ -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;
}
}
}