cloudTower申请虚拟机流程

develop
guyuliang 2024-05-29 16:13:51 +08:00
parent 3116e622ef
commit 4b6bf6bb54
10 changed files with 1231 additions and 8 deletions

View File

@ -126,6 +126,15 @@ public class Cluster extends GenericEntity {
private String memUsage;
// fc 纳管
@IgnoreAll
private Long cpuRemainder;
@IgnoreAll
private Long memoryRemainder;
@IgnoreAll
private Long diskRemainder;
@IgnoreAll
private List<Server> servers;
/**
* @param creatorId
* @param ownerId

View File

@ -164,6 +164,16 @@ public class DataStore extends GenericEntity {
@IgnoreAll
private String version;
@IgnoreAll
private Long SpaceRemain;
public Long getSpaceRemain() {
return SpaceRemain;
}
public void setSpaceRemain(Long spaceRemain) {
SpaceRemain = spaceRemain;
}
/**
* @return the vdcId

View File

@ -300,6 +300,10 @@ public class Server extends GenericEntity {
private String cpuTotalMhz;
@IgnoreAll
private CloudVendor vendor;
public void preSave(Long creatorId, Long menderId, Long vendorId, Long vdcId, Long clusterId) {
this.setCreatorId(creatorId);

View File

@ -81,6 +81,15 @@ public class Vdc extends GenericEntity {
private String mgntNetworkType;//管理面ip版本取值ipv4,ipv6
//fc新增字段
@IgnoreAll
private Long cpuRemainder;
@IgnoreAll
private Long memoryRemainder;
@IgnoreAll
private Long diskRemainder;
@IgnoreAll
private List<Server> servers;
/**
* @return the id
*/

View File

@ -11,6 +11,7 @@ import com.bocloud.database.core.intf.impl.BasicGenericDao;
import com.bocloud.database.utils.QueryBuilder;
import com.bocloud.ims.entity.resource.Network;
import com.bocloud.ims.entity.resource.Server;
import com.bocloud.orm.OrmGenericDaoImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
@ -30,7 +31,7 @@ import java.util.Map;
*
*/
@Repository("networkRepository")
public class NetworkRepository extends BasicGenericDao<Network, Long> {
public class NetworkRepository extends OrmGenericDaoImpl<Network, Long> {
public NetworkRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate) {
super(jdbcTemplate, npJdbcTemplate);

View File

@ -4,6 +4,7 @@ import com.bocloud.common.utils.ListTool;
import com.bocloud.common.utils.MapTools;
import com.bocloud.database.core.intf.impl.BasicGenericDao;
import com.bocloud.ims.entity.resource.ServerConfig;
import com.bocloud.orm.OrmGenericDaoImpl;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;
@ -20,7 +21,7 @@ import java.util.Map;
*
*/
@Repository("serverConfigRepository")
public class ServerConfigRepository extends BasicGenericDao<ServerConfig, Long> {
public class ServerConfigRepository extends OrmGenericDaoImpl<ServerConfig, Long> {
public ServerConfigRepository(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate npJdbcTemplate) {
super(jdbcTemplate, npJdbcTemplate);

View File

@ -0,0 +1,471 @@
package com.bocloud.ims.service.builder;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.compute.ServerDriver;
import com.bocloud.cmp.driver.compute.ServerTemplateDriver;
import com.bocloud.cmp.driver.storage.VolumeDriver;
import com.bocloud.cmp.model.NetworkCardModel;
import com.bocloud.cmp.model.ServerModel;
import com.bocloud.cmp.model.VolumeModel;
import com.bocloud.cmp.vm.model.VmGenericParam;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.model.RequestContext;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.repository.resource.*;
import com.bocloud.ims.service.transporter.vendor.CloudTowerTransporter;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* cloudTower
*/
public class CloudTowerServerBuilder implements ServerBuilder {
private static final Logger logger = LoggerFactory.getLogger(CloudTowerServerBuilder.class);
private final CloudVendorRepository cloudVendorRepository;
private final ServerRepository serverRepository;
private final CloudServerRepository cloudServerRepository;
private final ClusterRepository clusterRepository;
private final VolumeRepository volumeRepository;
private final VolumeTemplateRepository volumeTemplateRepository;
private final ImageRepository imageRepository;
private final SwitcherRepository switcherRepository;
private final NetworkRepository networkRepository;
private final NetworkCardRepository networkCardRepository;
private final SubnetRepository subnetRepository;
private final ServerVolumeRepository serverVolumeRepository;
private final ServerImageRepository serverImageRepository;
private final ServerDriver serverDriver;
private final VolumeDriver volumeDriver;
private final ServerTemplateDriver serverTemplateDriver;
private final CloudTowerTransporter cloudTowerTransporter;
private final RequestContext context;
private CloudVendor vendor;
private VmGenericParam vmGenericParam;
private ServerModel serverModel;
public CloudTowerServerBuilder(CloudVendorRepository cloudVendorRepository, ServerRepository serverRepository,
CloudServerRepository cloudServerRepository, VolumeRepository volumeRepository,
VolumeTemplateRepository volumeTemplateRepository, ImageRepository imageRepository,
SwitcherRepository switcherRepository, NetworkRepository networkRepository,
SubnetRepository subnetRepository, ServerVolumeRepository serverVolumeRepository,
ServerImageRepository serverImageRepository, ServerDriver serverDriver,
VolumeDriver volumeDriver, ServerTemplateDriver serverTemplateDriver,
CloudTowerTransporter cloudTowerTransporter, RequestContext context,
ClusterRepository clusterRepository, NetworkCardRepository networkCardRepository) {
this.cloudVendorRepository = cloudVendorRepository;
this.serverRepository = serverRepository;
this.cloudServerRepository = cloudServerRepository;
this.volumeRepository = volumeRepository;
this.volumeTemplateRepository = volumeTemplateRepository;
this.imageRepository = imageRepository;
this.switcherRepository = switcherRepository;
this.networkRepository = networkRepository;
this.subnetRepository = subnetRepository;
this.serverVolumeRepository = serverVolumeRepository;
this.serverImageRepository = serverImageRepository;
this.serverDriver = serverDriver;
this.volumeDriver = volumeDriver;
this.serverTemplateDriver = serverTemplateDriver;
this.cloudTowerTransporter = cloudTowerTransporter;
this.context = context;
this.clusterRepository = clusterRepository;
this.networkCardRepository = networkCardRepository;
}
@Override
public BocloudResult<ServerModel> prepare(JSONObject object) throws Exception {
try {
VmGenericParam vmGenericParam = object.toJavaObject(VmGenericParam.class);
Long sourceServerId = null;
ServerModel serverModel = new ServerModel();
Cluster cluster = null;
if (vmGenericParam.getTemplateId() != null) {
// 从模板创建云主机
sourceServerId = vmGenericParam.getTemplateId();
CloudServer template = cloudServerRepository.query(vmGenericParam.getTemplateId());
Assert.notNull(template, "id为" + vmGenericParam.getTemplateId() + "云主机模板不存在");
vmGenericParam.setVendorId(template.getVendorId());
serverModel.setInstanceId(template.getInstanceId());
cluster = clusterRepository.query(vmGenericParam.getClusterId());
Assert.notNull(cluster, "id为" + vmGenericParam.getClusterId() + "集群不存在");
serverModel.setClusterUuid(cluster.getUuid());
if (vmGenericParam.getFullClone() == null) {
vmGenericParam.setFullClone(true);
}
if (vmGenericParam.getFullClone() && vmGenericParam.getServerId() == 0) {
return new BocloudResult<>(false, "完全拷贝克隆需要明确指定目标云主机所属主机");
}
serverModel.setFullClone(vmGenericParam.getFullClone());
serverModel.setVmHostName(vmGenericParam.getVmHostName());
serverModel.setPassword(vmGenericParam.getPassword());
}
vendor = cloudVendorRepository.query(vmGenericParam.getVendorId());
Assert.notNull(vendor, "ID为" + vmGenericParam.getVendorId() + "云平台不存在");
Assert.notNull(vmGenericParam.getName(), "需要为云主机指定名称");
CloudServer vmbyName = cloudServerRepository.getByName(vmGenericParam.getName(), vendor.getId());
Assert.isNull(vmbyName, "名为" + vmGenericParam.getName() + "的云主机已经存在,请重新命名");
serverModel.setName(vmGenericParam.getName());
if (vmGenericParam.getHa() == null) {
vmGenericParam.setHa(true);
}
serverModel.setHa(vmGenericParam.getHa());
Assert.notNull(vmGenericParam.getServerId(), "需要为云主机指定所属主机");
if (vmGenericParam.getServerId() == 0) {
serverModel.setAutoSchedule(true);
} else {
Server host = serverRepository.query(vmGenericParam.getServerId());
Assert.notNull(host, "id为" + vmGenericParam.getServerId() + "主机不存在");
serverModel.setHostIp(host.getVmotionIp());
serverModel.setHostUuid(host.getUuid());
}
Assert.notNull(vmGenericParam.getCpu(), "需要为云主机指定CPU配置");
serverModel.setCpu(vmGenericParam.getCpu());
Assert.notNull(vmGenericParam.getMemory(), "需要为云主机指定内存配置");
serverModel.setMemory(vmGenericParam.getMemory());
Assert.notNull(vmGenericParam.getFirmware(), "需要为云主机指定引导选项");
serverModel.setFirmware(vmGenericParam.getFirmware());
Assert.notNull(vmGenericParam.getStatus(), "参数status不能为空");
serverModel.setStatus(vmGenericParam.getStatus());
if (StringUtils.isNotEmpty(vmGenericParam.getRemark())) {
serverModel.setRemark(vmGenericParam.getRemark());
}
Assert.notEmpty(vmGenericParam.getDiskDevices(), "需要为云主机定义虚拟盘");
List<VolumeModel> disks = new ArrayList<>();
for (int i = 0; i < vmGenericParam.getDiskDevices().size(); i++) {
VolumeModel diskDevice = vmGenericParam.getDiskDevices().get(i);
VolumeModel disk = new VolumeModel();
disk.setType(diskDevice.getType());
if ("reserveDisk".equals(diskDevice.getType())) {
Assert.notNull(diskDevice.getId(), "需要指定要保留的虚拟卷");
Volume volume = volumeRepository.query(diskDevice.getId());
Assert.notNull(volume, "id为" + diskDevice.getId() + "的虚拟卷不存在");
ServerVolume serverVolume = serverVolumeRepository
.getByServerIdAndVolumeId(sourceServerId, volume.getId());
Assert.notNull(serverVolume, "id为" + diskDevice.getId() + "的虚拟卷并未挂载当前云主机");
disk.setPath(volume.getPath());
disk.setTemplateUuid(serverVolume.getTemplateUuid());
if (StringUtils.isNotEmpty(diskDevice.getName())) {
disk.setName(diskDevice.getName());
} else {
disk.setName(volume.getName());
}
if (StringUtils.isNotEmpty(diskDevice.getBus())) {
disk.setBus(diskDevice.getBus());
} else {
disk.setBus(serverVolume.getBus());
}
} else if ("removeDisk".equals(diskDevice.getType())) {
Assert.notNull(diskDevice.getId(), "需要指定要删除的虚拟卷");
Volume volume = volumeRepository.query(diskDevice.getId());
Assert.notNull(volume, "id为" + diskDevice.getId() + "的虚拟卷不存在");
ServerVolume serverVolume = serverVolumeRepository
.getByServerIdAndVolumeId(sourceServerId, volume.getId());
Assert.notNull(serverVolume, "id为" + diskDevice.getId() + "的虚拟卷并未挂载当前云主机");
disk.setPath(volume.getPath());
} else if ("reserveISO".equals(diskDevice.getType())) {
Assert.notNull(diskDevice.getDiffKey(), "需要指定要保留的ISO映像的KEY");
List<ServerImage> serverImages = serverImageRepository.listByServerId(sourceServerId);
ServerImage serverImage = serverImages.stream()
.filter(si -> diskDevice.getDiffKey().equals(si.getDiffKey())).findFirst().orElse(null);
Assert.notNull(serverImage, "KEY为" + diskDevice.getDiffKey() + "的ISO映像不存在");
disk.setKey(serverImage.getDiffKey());
disk.setBus(serverImage.getBus());
if (diskDevice.getId() != null) {
Image image = imageRepository.query(diskDevice.getId());
Assert.notNull(image, "id为" + diskDevice.getId() + "的ISO映像不存在");
disk.setPath(image.getFilePath());
}
if (diskDevice.getDisabled() != null) {
disk.setDisabled(diskDevice.getDisabled());
} else {
disk.setDisabled(serverImage.getDisabled());
}
} else if ("removeISO".equals(diskDevice.getType())) {
Assert.notNull(diskDevice.getDiffKey(), "需要指定要删除的ISO映像的KEY");
List<ServerImage> serverImages = serverImageRepository.listByServerId(sourceServerId);
ServerImage serverImage = serverImages.stream()
.filter(si -> diskDevice.getDiffKey().equals(si.getDiffKey())).findFirst().orElse(null);
Assert.notNull(serverImage, "KEY为" + diskDevice.getDiffKey() + "的ISO映像不存在");
disk.setKey(serverImage.getDiffKey());
Image image = imageRepository.query(serverImage.getImageId());
Assert.notNull(image, "id为" + diskDevice.getId() + "的ISO映像不存在");
if ("HIDE".equals(image.getCatalog())) {
disk.setPath("");
} else {
disk.setPath(image.getFilePath());
}
} else if ("newDisk".equals(diskDevice.getType())) {
diskDevice.setName(vmGenericParam.getName() + "_disk" + i);
Assert.notNull(diskDevice.getName(), "需要为新建的虚拟卷指定名称");
Volume volumeByName = volumeRepository.getByName(vendor.getId(), diskDevice.getName());
Assert.isNull(volumeByName, "名为" + diskDevice.getName() + "的虚拟卷已经存在,请重新命名");
disk.setName(diskDevice.getName());
disk.setSize(diskDevice.getSize());
if (disk.getSize() == null){
disk.setSize(diskDevice.getDisk());
}
Assert.notNull(disk.getSize(), "需要为新建的虚拟卷指定容量");
disk.setBlockSize(1D);
disk.setBlockCount(disk.getSize() * 1024L * 1024L * 1024L);
Assert.notNull(diskDevice.getBus(), "需要为新建的虚拟卷指定总线");
disk.setBus(diskDevice.getBus());
Assert.notNull(diskDevice.getVolumeTemplateId(), "需要为新建的虚拟卷指定存储策略");
VolumeTemplate volumeTemplate = volumeTemplateRepository.get(diskDevice.getVolumeTemplateId());
Assert.notNull(volumeTemplate, "id为" + diskDevice.getVolumeTemplateId() + "的存储策略不存在");
disk.setVolumeTemplateUuid(volumeTemplate.getUuid());
} else if ("mountDisk".equals(diskDevice.getType())) {
Assert.notNull(diskDevice.getId(), "需要指定要挂载的虚拟卷");
Volume volume = volumeRepository.query(diskDevice.getId());
Assert.notNull(volume, "id为" + diskDevice.getId() + "的虚拟卷不存在");
disk.setPath(volume.getPath());
Assert.notNull(diskDevice.getBus(), "需要为新建的虚拟卷指定总线");
disk.setBus(diskDevice.getBus());
} else if ("mountISO".equals(diskDevice.getType())) {
disk.setBus("ide");
Assert.notNull(diskDevice.getId(), "需要指定要挂载的ISO映像");
Image image = imageRepository.query(diskDevice.getId());
Assert.notNull(image, "id为" + diskDevice.getId() + "的ISO映像不存在");
disk.setPath(image.getFilePath());
Assert.notNull(diskDevice.getDisabled(), "需要参数diskDevices.disabled");
disk.setDisabled(diskDevice.getDisabled());
} else {
return new BocloudResult<>(false, "未知的虚拟盘类型");
}
disks.add(disk);
}
serverModel.setDiskDevices(disks);
/**
*
*/
// 根据集群查询网卡信息
Network network1 = null;
if (cluster != null) {
network1 = networkRepository.queryProxy()
.col(Network::getClusterUuid).eq(cluster.getUuid())
.col(Network::getType).eq("VM")
.col(Network::getDeleted).eq(false)
.list().get(0);
}
Assert.notEmpty(vmGenericParam.getNetworkCards(), "需要为云主机定义虚拟网卡");
for (NetworkCardModel netcard : vmGenericParam.getNetworkCards()) {
Assert.notNull(netcard.getNetworkId(), "需要为虚拟网卡指定网络");
Network network = networkRepository.query(netcard.getNetworkId());
Assert.notNull(network, "未找到id为" + netcard.getNetworkId() + "的虚拟网络");
if (network1 != null) {
logger.info("当前虚拟网络为:{}", JSONObject.toJSONString(network1));
netcard.setNetworkUuid(network1.getNetworkUuid());
} else {
netcard.setNetworkUuid(network.getNetworkUuid());
}
}
serverModel.setNetworkCards(vmGenericParam.getNetworkCards());
this.serverModel = serverModel;
this.vmGenericParam = vmGenericParam;
object.remove("id");
return new BocloudResult<>(true, serverModel, "success");
} catch (Exception e) {
logger.error("Prepare Cloud-Tower云主机失败{}", e.getMessage(), e);
return new BocloudResult<>(false, e.getMessage());
}
}
@Override
public BocloudResult<CloudServer> builder(CloudServer server) throws Exception {
try {
String vlan = "";
try {
List<NetworkCardModel> networkCards = server.getNetworkCards();
for (NetworkCardModel networkCard : networkCards) {
vlan = networkRepository.query(networkCard.getNetworkId()).getName();
break;
}
logger.info("获取vlan名称成功");
} catch (Exception e) {
logger.error("获取vlan名称失败", e);
}
// 执行创建
BocloudResult createResult;
if (vmGenericParam.getTemplateId() != null) {
logger.info("serverModel:{}", JSON.toJSONString(serverModel));
// 从模板创建云主机
createResult = serverDriver
.create(vendor.getUuid(), null, serverModel.getInstanceId(), serverModel);
Assert.isTrue(createResult.isSuccess(), createResult.getMessage());
} else if (vmGenericParam.getId() != null) {
// 从云主机克隆云主机
createResult = serverDriver.cloneAsVm(vendor.getUuid(), null, serverModel);
Assert.isTrue(createResult.isSuccess(), createResult.getMessage());
} else {
// 创建空白云主机
createResult = serverDriver.create(vendor.getUuid(), null, serverModel);
Assert.isTrue(createResult.isSuccess(), createResult.getMessage());
}
// 获取云主机数据
ServerModel serverModel = (ServerModel) createResult.getData();
if (vmGenericParam.getTemplateId() != null) {
// 从模板创建云主机
}
// 查询所属宿主机
String serverIp = serverModel.getServerVal();
Server host = serverRepository.queryBy3Ip(serverIp);
Assert.notNull(host, "未找到IP为" + serverIp + "的主机");
// 保存云主机数据
cloudTowerTransporter.convert(serverModel, server);
// 获取IP信息
if(StringUtils.isBlank(serverModel.getManagerIp())) {
logger.info("开始获取tower虚拟机IP地址......");
while (true) {
BocloudResult detail = serverDriver.detail(serverModel.getInstanceId(), vendor.getUuid(), null);
if (detail.isSuccess()) {
ServerModel model = (ServerModel) detail.getData();
if (StringUtils.isBlank(model.getManagerIp())) {
Thread.sleep(3000L);
} else {
logger.info("获取tower虚拟机IP地址成功{}......",model.getManagerIp());
// 保存云主机数据
cloudTowerTransporter.convert(model, server);
List<NetworkCardModel> netcards = model.getNetcards();
List<NetworkCard> networkCardList = new ArrayList<>();
for (NetworkCardModel netcard : netcards) {
NetworkCard networkCard = new NetworkCard();
networkCard.setCategory("VM");
networkCard.setHostId(server.getId());
networkCard.setName(vlan);
networkCard.setCreatorId(context.getTarget());
networkCard.setSubnetUuid(netcard.getSubnetUuid());
networkCard.setInstanceId(netcard.getInstanceId());
networkCard.setVlan(netcard.getVlan());
networkCard.setNetmask(netcard.getNetmask());
networkCard.setIpAddress(netcard.getIpAddress());
networkCard.setModel(netcard.getModel());
networkCard.setUsed(netcard.getUsed());
networkCard.setMac(netcard.getMac());
networkCard.setNetworkcardUuid(netcard.getNetworkcardUuid());
networkCard.setVendorId(vendor.getId());
networkCard.setGmtCreate(new Date());
networkCard.setDeleted(false);
networkCardList.add(networkCard);
}
for (NetworkCard networkCard : networkCardList) {
networkCardRepository.save(networkCard);
}
logger.info(server.getName() + ":创建虚拟机添加网卡成功");
break;
}
}
}
}
server.setHostId(host.getId());
server.setVendorId(vendor.getId());
server.setVendorType(vendor.getType());
cloudServerRepository.update(server);
// 保存新建的虚拟卷数据
/* for (Map.Entry<String, Object> taskResourceEntry : taskResource.entrySet()) {
String taskResourceUuid = taskResourceEntry.getKey();
if (taskResourceUuid.equals(server.getInstanceId())) {
continue;
}
BocloudResult volumeResult = volumeDriver.detail(taskResourceUuid, vendor.getUuid(), null);
Assert.isTrue(volumeResult.isSuccess(), volumeResult.getMessage());
VolumeModel volumeModel = (VolumeModel) volumeResult.getData();
if (volumeModel != null) {
logger.info("查询名为[{}]cloudTower卷大小为{}", volumeModel.getName(), volumeModel.getSize());
Volume existsVolume = volumeRepository.getByVolumeUuid(volumeModel.getUuid());
if (existsVolume == null) {
String volumeTemplateUuid = volumeModel.getVolumeTemplateUuid();
VolumeTemplate volumeTemplate = volumeTemplateRepository.getByUuid(volumeTemplateUuid);
Assert.notNull(volumeTemplate, "未找到UUID为" + volumeTemplateUuid + "的存储策略");
Volume volume = new Volume();
cloudTowerTransporter.convert(volumeModel, volume);
volume.setVendorId(vendor.getId());
volume.setTemplateId(volumeTemplate.getId());
volume.setCreatorId(context.getTarget());
volume.setGmtCreate(new Date());
volume.setRegionId(server.getRegionId());
volume.setRegion(server.getRegionId());
volumeRepository.save(volume);
}
}
}*/
// 保存云主机网卡数据
// cloudTowerTransporter.syncNetworkCard(server, Optional.ofNullable(serverModel.getNetworkCards()).orElse(new ArrayList<>()), context.getTarget());
// 保存云主机关联ISO镜像
List<VolumeModel> imageModels = Optional.ofNullable(serverModel.getDiskDevices()).orElse(new ArrayList<>()).stream()
.filter(d -> "cdrom".equalsIgnoreCase(d.getType())).collect(Collectors.toList());
cloudTowerTransporter.syncServerImage(server, imageModels, context.getTarget());
// 保存云主机关联虚拟盘
List<VolumeModel> volumeModels = Optional.ofNullable(serverModel.getDiskDevices()).orElse(new ArrayList<>()).stream()
.filter(d -> "disk".equalsIgnoreCase(d.getType())).collect(Collectors.toList());
for (VolumeModel volumeModel : volumeModels) {
String volumeUuid = volumeModel.getVolumeUuid();
Volume volume = volumeRepository.getByVolumeUuid(volumeUuid);
Optional<VolumeTemplate> dbVolumeTemplateOpt = Optional.of(volumeModel)
.map(VolumeModel::getVolumeTemplateUuid).map(volumeTemplateRepository::getByName);
if (volume == null) {
volume = new Volume();
cloudTowerTransporter.convert(volumeModel, volume);
volume.setVendorId(vendor.getId());
volume.setServerId(server.getId());
volume.setVendorId(server.getVendorId());
volume.setInstanceId(server.getInstanceId());
volume.setTemplateId(dbVolumeTemplateOpt.isPresent() ? dbVolumeTemplateOpt.get().getId() : null);
volume.setCreatorId(context.getTarget());
volume.setGmtCreate(new Date());
volume.setRegionId(server.getRegionId());
volume.setRegion(server.getRegionId());
volumeRepository.save(volume);
}
}
cloudTowerTransporter.syncServerVolume(server, volumeModels, context.getTarget());
return new BocloudResult<>(true, server, "success");
} catch (Exception e) {
logger.error("Build cloudTower云主机失败{}", e.getMessage(), e);
return new BocloudResult<>(false, server, e.getMessage());
}
}
}

View File

@ -0,0 +1,28 @@
package com.bocloud.ims.service.engine;
import com.bocloud.cmp.model.common.AssignResult;
import com.bocloud.ims.entity.resource.DataStore;
import lombok.Data;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Data
public class AssignResultManager {
private AssignResult assignResult;
private Map<Long, Long> dataStoreSpaceCache = new HashMap<>();
public void save(List<DataStore> dataStoreList){
dataStoreSpaceCache.clear();
for (DataStore dataStore : dataStoreList) {
dataStoreSpaceCache.put(dataStore.getId(), dataStore.getSpaceRemain());
}
}
public void rollback(List<DataStore> dataStoreList){
for (DataStore dataStore : dataStoreList) {
dataStore.setSpaceRemain(dataStoreSpaceCache.get(dataStore.getId()));
}
}
}

View File

@ -2,13 +2,20 @@ package com.bocloud.ims.service.engine;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.driver.compute.HostDriver;
import com.bocloud.cmp.driver.storage.DataStoreDriver;
import com.bocloud.cmp.entity.enums.BocloudStatus;
import com.bocloud.cmp.entity.enums.CloudProvider;
import com.bocloud.cmp.entity.enums.PoolGroupTarget;
import com.bocloud.cmp.model.DataStoreModel;
import com.bocloud.cmp.model.HostOperateModel;
import com.bocloud.cmp.model.common.AssignDataDiskParam;
import com.bocloud.cmp.model.common.AssignDataDiskResult;
import com.bocloud.cmp.model.common.AssignParam;
import com.bocloud.cmp.model.common.AssignResult;
import com.bocloud.common.model.BocloudResult;
import com.bocloud.common.utils.ListTool;
import com.bocloud.entity.bean.GenericEntity;
import com.bocloud.ims.entity.resource.*;
import com.bocloud.ims.interfaces.resource.VMExtendService;
import com.bocloud.ims.repository.resource.*;
@ -19,9 +26,11 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
@ -51,6 +60,7 @@ import java.util.stream.Collectors;
@Autowired private SwitcherRepository switcherRepository;
@Autowired private NetworkHostRepository networkHostRepository;
@Autowired private VMExtendService vmExtendService;
@Autowired private HostDriver hostDriver;
/**
*
@ -580,4 +590,613 @@ import java.util.stream.Collectors;
return new BocloudResult<>(true, targetObjs, "success");
}
/**
*
*
* @param assignParamList
* @return
*/
public List<AssignResult> assign(PoolGroup group, CloudVendor vendor, List<AssignParam> assignParamList) throws Exception {
// 查询策略是否存在
SchedulerPolicy schedulerPolicy = schedulerPolicyRepository.query(group.getPolicyId());
Assert.notNull(schedulerPolicy, "策略不存在");
// 过滤出资源池下关联的主机和数据存储
List<PoolGroupRelation> relations = relationRepository.listByGroupId(group.getId());
Set<Long> clusterIds = relations.stream().filter(PoolGroupRelation::getEnabled)
.filter(relation -> PoolGroupTarget.Cluster.name().equalsIgnoreCase(relation.getCategory()))
.map(PoolGroupRelation::getTarget)
.collect(Collectors.toSet());
//查询可以调度的宿主机
List<Server> hostList = serverRepository.queryProxy()
.col(GenericEntity::getStatus).eq(BocloudStatus.Server.RUNNING.name())
.col(Server::getClusterId).in(clusterIds).col(GenericEntity::getDeleted).notEq(1)
.list();
String sort = "Memory";
List<AssignResult> resultObjs = configAndAssign(sort, group.getRelationType(), SchedulerPolicy.policy.valueOf(schedulerPolicy.getPolicy()), vendor, assignParamList, hostList);
return resultObjs;
}
/**
*
*
* @return
*/
private List<AssignResult> configAndAssign(String sort, String resourceRelationType, SchedulerPolicy.policy schedulerPolicy, CloudVendor vendor, List<AssignParam> assignParamList, List<Server> hostList) {
configVendor(vendor, hostList);
// logger.info("hostList:{}", JSON.toJSONString(hostList));
//查询ServerConfig
configHosts(hostList);
// logger.info("hostList:{}", JSON.toJSONString(hostList));
//查询宿主机下的虚拟机
associateHostVms(hostList);
// logger.info("hostList:{}", JSON.toJSONString(hostList));
//关联宿主机下的存储
associateHostDataStores(hostList);
// logger.info("hostList:{}", JSON.toJSONString(hostList));
hostList = calculateHostsRemainingResource(vendor, hostList);
logger.info("资源变更分配宿主机列表:{}", JSON.toJSONString(hostList));
List<AssignResult> resultObjs = doAssign(sort, assignParamList, resourceRelationType, schedulerPolicy, hostList);
logger.info("resultObjs:{}", JSON.toJSONString(resultObjs));
return resultObjs;
}
/**
*
* DataStore,
*
* @return
*/
private AssignResult assignSystemAndDataDiskStore(AssignParam assignParam, Server server) {
AssignResultManager assignResultManager = new AssignResultManager();
AssignResult assignResult = new AssignResult();
assignResult.setSuccess(false);
//获取计算过最新剩余大小的存储,且应该都是可用的
List<DataStore> dataStoreList = server.getDataStores();
assignResultManager.save(dataStoreList);
//按照剩余空间从大到小排
dataStoreList.sort((o1, o2) -> o2.getSpaceRemain().compareTo(o1.getSpaceRemain()));
for (DataStore dataStore : dataStoreList) {
if (dataStore.getSpaceRemain() > assignParam.getDisk()) {
dataStore.setSpaceRemain(dataStore.getSpaceRemain() - assignParam.getDisk());
assignResult.setStoreId(dataStore.getId());
break;
}
}
//系统盘分配出来了才继续往下分配
if (assignResult.getStoreId() != null) {
List<AssignDataDiskParam> dataDiskParams = assignParam.getDataDiskParams();
List<AssignDataDiskResult> assignDataDiskResultList = new ArrayList<>();
if (!CollectionUtils.isEmpty(dataDiskParams)) {
for (AssignDataDiskParam dataDiskParam : dataDiskParams) {
//每次都重新排序获取最大的存储
dataStoreList.sort((o1, o2) -> o2.getSpaceRemain().compareTo(o1.getSpaceRemain()));
for (DataStore dataStore : dataStoreList) {
if (dataStore.getSpaceRemain() > dataDiskParam.getSize()) {
//保存storeName
dataStore.setSpaceRemain(dataStore.getSpaceRemain() - dataDiskParam.getSize());
AssignDataDiskResult diskResult = new AssignDataDiskResult();
diskResult.setHostId(server.getId());
diskResult.setStoreId(dataStore.getId());
diskResult.setSize(dataDiskParam.getSize());
diskResult.setStoreName(dataStore.getName());
diskResult.setStoreDeviceUuid(dataStore.getGuid());
//设置关联的申请参数
diskResult.setAssignDataDiskParam(dataDiskParam);
assignDataDiskResultList.add(diskResult);
break;
}
}
}
}
assignResult.setAssignDataDiskResultList(assignDataDiskResultList);
//申请数量和分配数量一致才算成功
if (!CollectionUtils.isEmpty(dataDiskParams)) {
assignResult.setSuccess(dataDiskParams.size() == assignDataDiskResultList.size());
} else {
assignResult.setSuccess(true);
}
}
//分配失败,回滚空间
if (!assignResult.getSuccess()) {
assignResultManager.rollback(dataStoreList);
}
return assignResult;
}
private <T> void sortCommon(List<T> resource, String sort, Boolean reverse, Function<T, Long> getCpuRemainder, Function<T, Long> getMemoryRemainder, Function<T, Long> getDiskRemainder) {
Collections.sort(resource, (first, second) -> {
if (null == first || second == null) {
return 0;
}
Long preCpuRemainder = getCpuRemainder.apply(first);
Long preMemRemainder = getMemoryRemainder.apply(first);
Long preDiskRemainder = getDiskRemainder.apply(first);
Long nextCpuRemainder = getCpuRemainder.apply(second);
Long nextMemRemainder = getCpuRemainder.apply(second);
Long nextDiskRemainder = getCpuRemainder.apply(second);
if (reverse) {
preCpuRemainder = getCpuRemainder.apply(second);
preMemRemainder = getCpuRemainder.apply(second);
preDiskRemainder = getCpuRemainder.apply(second);
nextCpuRemainder = getCpuRemainder.apply(first);
nextMemRemainder = getMemoryRemainder.apply(first);
nextDiskRemainder = getMemoryRemainder.apply(first);
}
if ("Cpu".equalsIgnoreCase(sort)) {
return nextCpuRemainder.compareTo(preCpuRemainder);
} else if ("Memory".equalsIgnoreCase(sort)) {
return nextMemRemainder.compareTo(preMemRemainder);
} else if ("Disk".equalsIgnoreCase(sort)) {
return nextDiskRemainder.compareTo(preDiskRemainder);
} else {
return nextCpuRemainder.compareTo(preCpuRemainder);
}
});
}
private void sortWithType(List<Server> hosts, String sort, Boolean reverse, String type) {
if (type != null) {
type = type.toLowerCase();
//根据不同资源类型进行分散分配
switch (type) {
case "cluster":
Map<Long, List<Server>> clusterGroup = hosts.stream().collect(Collectors.groupingBy(Server::getClusterId));
//宿主机按照集群分组
List<Cluster> clusterList = clusterGroup.keySet().stream().map(clusterId -> {
List<Server> servers = clusterGroup.get(clusterId);
Cluster cluster = new Cluster();
cluster.setId(clusterId);
cluster.setCpuRemainder(servers.stream().mapToLong(Server::getCpuRemainder).sum());
cluster.setMemoryRemainder(servers.stream().mapToLong(Server::getMemoryRemainder).sum());
cluster.setDiskRemainder(servers.stream().mapToLong(Server::getDiskRemainder).sum());
cluster.setHostNum(servers.size());
//排序集群下宿主机
sort(servers, sort, reverse);
cluster.setServers(servers);
return cluster;
}).collect(Collectors.toList());
//先排序集群
sortCommon(clusterList, sort, reverse, Cluster::getCpuRemainder, Cluster::getMemoryRemainder, Cluster::getDiskRemainder);
//按照集群维度分散分配
int maxSize = clusterList.stream().mapToInt(Cluster::getHostNum).max().orElse(0);
List<Server> newHosts = new ArrayList<>();
for (int i = 0; i < maxSize; i++) {
for (Cluster cluster : clusterList) {
if (!CollectionUtils.isEmpty(cluster.getServers())) {
//每次获取剩余资源最大的宿主机
Server server = cluster.getServers().remove(0);
newHosts.add(server);
}
}
}
//为了适配上层调用,这里暂时只能使用这种方式改变排序结果
hosts.clear();
hosts.addAll(newHosts);
break;
case "vdc":
Map<Long, List<Server>> vdcGroup = hosts.stream().collect(Collectors.groupingBy(Server::getVdcId));
//宿主机按照集群分组
List<Vdc> vdcList = vdcGroup.keySet().stream().map(vdcId -> {
List<Server> servers = vdcGroup.get(vdcId);
Vdc vdc = new Vdc();
vdc.setId(vdcId);
vdc.setCpuRemainder(servers.stream().mapToLong(Server::getCpuRemainder).sum());
vdc.setMemoryRemainder(servers.stream().mapToLong(Server::getMemoryRemainder).sum());
vdc.setDiskRemainder(servers.stream().mapToLong(Server::getDiskRemainder).sum());
vdc.setHostNum((long) servers.size());
vdc.setServers(servers);
return vdc;
}).collect(Collectors.toList());
//先排序集群
sortCommon(vdcList, sort, reverse, Vdc::getCpuRemainder, Vdc::getMemoryRemainder, Vdc::getDiskRemainder);
//按照VDC维度分散分配
long maxVdcHosts = vdcList.stream().mapToLong(Vdc::getHostNum).max().orElse(0);
List<Server> newVdcHost = new ArrayList<>();
for (int i = 0; i < maxVdcHosts; i++) {
for (Vdc vdc : vdcList) {
if (i < vdc.getHostNum()) {
Server server = vdc.getServers().get(i);
newVdcHost.add(server);
}
}
}
//为了适配上层调用,这里暂时只能使用这种方式改变排序结果
hosts.clear();
hosts.addAll(newVdcHost);
break;
case "host":
default:
this.sort(hosts, sort, reverse);
}
}
}
private List<AssignResult> doAssign(String sort, List<AssignParam> assignParamList, String resourceRelationType, SchedulerPolicy.policy policy, List<Server> hosts) {
List<AssignResult> assignResults = new ArrayList<>();
long cpuNeed = assignParamList.stream().mapToLong(param -> param.getCpu() * param.getInstance()).sum();
long memoryNeed = assignParamList.stream().mapToLong(param -> param.getMemory() * param.getInstance()).sum();
switch (policy) {
case focus:
// 对集群进行排序,如果用户选择资源密集型策略,则倒叙排列,然后取资源剩余最适合分配的那个集群,否则正序排列
this.sort(hosts, sort, true);
// 资源集中式分配不用考虑具体规格CPU内存等
for (Server host : hosts) {
logger.info("getCpuRemainder:" + host.getCpuRemainder());
logger.info("getMemoryRemainder:" + host.getMemoryRemainder());
logger.info("cpuNeed:" + cpuNeed);
logger.info("memoryNeed:" + memoryNeed);
if (cpuNeed <= host.getCpuRemainder()
&& memoryNeed <= host.getMemoryRemainder()) {
logger.info("");
for (AssignParam assignParam : assignParamList) {
AssignResult assignResult = new AssignResult();
assignResult.setHostId(host.getId());
assignResult.setVdcId(host.getVdcId());
assignResult.setClusterId(host.getClusterId());
AssignResult result = assignSystemAndDataDiskStore(assignParam, host);
Assert.isTrue(result.getSuccess(), "存储资源不足分配失败");
assignResult.setAssignId(assignParam.getUuid());
assignResult.setAssignParam(assignParam);
assignResults.add(assignResult);
}
break;
}
}
break;
case dispersion:
//与宿主机剩余资源排序保持一致,则剩余资源最大的宿主可以匹配占用资源最大的虚拟机
this.sortCommon(assignParamList, sort, false, AssignParam::getCpu, AssignParam::getMemory, AssignParam::getDisk);
this.sortWithType(hosts, sort, false, resourceRelationType);
for (AssignParam assignParam : assignParamList) {
assignParam.setRemain(assignParam.getInstance());
}
int retryCount = 0;
for (int i = 0; i < hosts.size() && retryCount < hosts.size() && assignResults.size() < assignParamList.size(); i++) {
Server host = hosts.get(i);
Long cpuRemainder = host.getCpuRemainder();
Long memoryRemainder = host.getMemoryRemainder();
boolean assigned = false;
// if (host.getVmRemainder() > 0) {
for (AssignParam assignParam : assignParamList) {
//判断宿主机剩余资源是否足够
if (assignParam.getRemain() > 0
&& assignParam.getCpu() <= cpuRemainder
&& assignParam.getMemory() <= memoryRemainder) {
AssignResult assignResult = this.assignSystemAndDataDiskStore(assignParam, host);
if (!assignResult.getSuccess()) {
continue;
}
assignResult.setHostId(host.getId());
assignResult.setVdcId(host.getVdcId());
assignResult.setAssignId(assignParam.getUuid());
assignResult.setAssignParam(assignParam);
assignResult.setClusterId(host.getClusterId());
assignResults.add(assignResult);
host.setCpuRemainder(cpuRemainder - assignParam.getCpu());
host.setMemoryRemainder(memoryRemainder - assignParam.getMemory());
assignParam.setRemain(assignParam.getRemain() - 1);
// host.setVmRemainder(host.getVmRemainder() - 1);
assigned = true;
//分配到一个之后就中断,分配下一个宿主机
break;
}
}
// }
if (!assigned) {
retryCount++;
} else {
retryCount = 0;
}
//重新回到第一个宿主机继续分配
if (i == hosts.size() - 1) {
i = -1;
}
}
break;
case random:
Server host = hosts.get(new Random().nextInt(hosts.size()));
for (AssignParam assignParam : assignParamList) {
AssignResult assignResult = new AssignResult();
assignResult.setHostId(host.getId());
assignResult.setVdcId(host.getVdcId());
assignResult.setClusterId(host.getClusterId());
List<DataStore> dataStoreList = host.getDataStores();
if (!CollectionUtils.isEmpty(dataStoreList)) {
DataStore dataStore = dataStoreList.get(new Random().nextInt(dataStoreList.size()));
assignResult.setStoreId(dataStore.getId());
}
assignResult.setAssignId(assignParam.getUuid());
assignResult.setAssignParam(assignParam);
assignResults.add(assignResult);
}
break;
default:
break;
}
return assignResults;
}
private void calculateHostRemain(CloudVendor cloudVendor, Server host, ServerConfig config, List<CloudServer> vms) {
long cpuTotal;
long memoryTotal = 0;
//计算资源剩余统计,安超的聚合组就是集群,
//cpu超分比默认取平台
Long cpuExcessRatio = cloudVendor.getExcessRatio();
//虚拟化比
// host.setVmRemainder(cloudVendor.getVirtualizationRatio().intValue());
// //统一计算剩余可分配虚拟机数量
// if (vms == null) {
// vms = new ArrayList<>();
// }
// host.setVmRemainder(host.getVmRemainder() - vms.size());
// 计算每个宿主机剩余可用cpu内存,存储容量,看是否有可分配的主机
int cpuUsed = vms.stream().mapToInt(CloudServer::getCpu).sum();
BigDecimal memUsed = null;
if (CloudProvider.VMWARE.name().equals(cloudVendor.getType())) {
HostOperateModel model = new HostOperateModel();
model.setHostName(host.getName());
try {
BocloudResult detail = hostDriver.detail(cloudVendor.getUuid(), null, model);
Assert.isTrue(detail.isSuccess(), detail.getMessage());
JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(detail.getData()));
if (jsonObject.getBigDecimal("memUsed") != null) {
memUsed = jsonObject.getBigDecimal("memUsed");
memoryTotal = jsonObject.getLong("memTotal");
logger.info("当前宿主机名称:" + host.getName() + ",已使用内存:" + memUsed + "G" + ",内存总量:" + memoryTotal + "G");
} else {
Assert.isTrue(false, "获取vmware宿主机详情失败");
}
} catch (Exception e) {
logger.error("获取vmware宿主机信息失败:", e);
Assert.isTrue(false, e.getMessage());
}
} else {
memUsed = vms.stream().map(CloudServer::getMemory).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
//内存没有超分比
memoryTotal = null == config.getMemoryCapacity() ? 0 :
BigDecimal.valueOf(config.getMemoryCapacity()).longValue();
}
cpuTotal = BigDecimal.valueOf(config.getCpuCore()).multiply(BigDecimal.valueOf(cpuExcessRatio)).longValue();
logger.info("cpuTotal:" + cpuTotal);
logger.info("cpuUsed:" + cpuUsed);
host.setCpuRemainder(Math.max(cpuTotal - cpuUsed, 0L));
// //判断当前内存使用量是否超出阈值设置
// if (BigDecimal.valueOf(memoryTotal).multiply(BigDecimal.valueOf(cloudVendor.getMemoryRatioPre())).divide(BigDecimal.valueOf(100)).compareTo(memUsed) <= 0) {
// host.setMemoryRemainder(0L);
// } else {
// // 使用分配后的阈值计算可以用内存的量
// memoryTotal = BigDecimal.valueOf(memoryTotal).multiply(BigDecimal.valueOf(cloudVendor.getMemoryRatioPost())).divide(BigDecimal.valueOf(100)).longValue();
//
logger.info("memoryTotal:" + memoryTotal);
logger.info("memUsed:" + memUsed);
host.setMemoryRemainder(Math.max(memoryTotal - memUsed.longValue(), 0L));
// }
}
private void calculateStoreRemain(CloudVendor vendor, DataStore store) {
// Long storageRatioPre = vendor.getStorageRatioPre();
BigDecimal spaceUsed = BigDecimal.valueOf(store.getCapacity() - store.getFreeSpace());
//判断已使用空间是否小于阈值
// if (BigDecimal.valueOf(store.getCapacity()).multiply(BigDecimal.valueOf(storageRatioPre))
// .divide(BigDecimal.valueOf(100)).compareTo(spaceUsed) > 0) {
//
// //计算剩余可用容量
// Long storageRatioPost = vendor.getStorageRatioPost();
//可用容量
BigDecimal availableSpace = BigDecimal.valueOf(store.getCapacity());
logger.info("availableSpace:" + availableSpace);
logger.info("spaceUsed:" + spaceUsed);
logger.info("spaceRemain" + availableSpace.subtract(spaceUsed).longValue());
store.setSpaceRemain(availableSpace.subtract(spaceUsed).longValue());
// } else {
// store.setSpaceRemain(0L);
// }
}
/**
* 宿,宿宿访
*
* @return true
*/
public boolean calculateHostRemainingResource(CloudVendor vendor, Server host) {
if (!BocloudStatus.Server.RUNNING.name().equals(host.getStatus())) {
return false;
}
ServerConfig config = host.getConfig();
if (null == config) {
return false;
}
List<CloudServer> vms = host.getServers();
calculateHostRemain(vendor, host, config, vms);
logger.info("host:{}", JSON.toJSONString(host));
List<DataStore> dataStoreList = host.getDataStores();
if (host.getCpuRemainder() >= 0 && host.getMemoryRemainder() >= 0) {
long diskTotalRemain = 0;
if (CollectionUtils.isEmpty(dataStoreList)) {
return false;
}
for (DataStore store : dataStoreList) {
calculateStoreRemain(vendor, store);
if (store.getSpaceRemain() > 0) {
//统计剩余容量
diskTotalRemain += store.getSpaceRemain();
}
}
logger.info("dataStoreList:{}", JSON.toJSONString(dataStoreList));
dataStoreList = dataStoreList.stream().filter(store -> store.getSpaceRemain() > 0).collect(Collectors.toList());
host.setDiskRemainder(Math.max(diskTotalRemain, 0L));
//新建存储和宿主机的关系
List<StoreHost> storeHosts = dataStoreList.stream().map(store -> {
StoreHost storeHost = new StoreHost();
storeHost.setVhostId(host.getId());
storeHost.setStoreId(store.getId());
return storeHost;
}).collect(Collectors.toList());
//设置新的关系
host.setStoreHosts(storeHosts);
host.setDataStores(dataStoreList);
return !dataStoreList.isEmpty();
}
return false;
}
public List<Server> calculateHostsRemainingResource(CloudVendor vendor, Collection<Server> hosts) {
List<Server> newHosts = new ArrayList<>();
for (Server host : hosts) {
// logger.info("host:{}", JSON.toJSONString(host));
if (calculateHostRemainingResource(vendor, host)) {
newHosts.add(host);
}
}
return newHosts;
}
/**
*
*
* @param cloudVendor
* @param hosts
*/
public void configVendor(CloudVendor cloudVendor, List<Server> hosts) {
JSONObject authentication = JSONObject.parseObject(cloudVendor.getAuthentication());
cloudVendor.setExcessRatio(Optional.ofNullable(authentication.getLong("excessRatio")).orElse(100L));
// cloudVendor.setVirtualizationRatio(Optional.ofNullable(authentication.getLong("virtualizationRatio")).orElse(100L));
// cloudVendor.setMemoryRatioPost(Optional.ofNullable(authentication.getLong("memoryRatioPost")).orElse(85L));
// cloudVendor.setMemoryRatioPre(Optional.ofNullable(authentication.getLong("memoryRatioPre")).orElse(80L));
// cloudVendor.setStorageRatioPost(Optional.ofNullable(authentication.getLong("storageRatioPost")).orElse(85L));
// cloudVendor.setStorageRatioPre(Optional.ofNullable(authentication.getLong("storageRatioPre")).orElse(80L));
for (Server host : hosts) {
host.setVendor(cloudVendor);
}
}
/**
* 宿config
*/
public void configHosts(Collection<Server> hosts) {
// 统一查询宿主机
Set<Long> hostIds = hosts.stream().map(Server::getId).collect(Collectors.toSet());
List<ServerConfig> list = null;
if (hostIds.isEmpty()) {
list = new ArrayList<>();
} else {
list = serverConfigRepository.queryProxy().col(ServerConfig::getServerId).in(hostIds).list();
}
Map<Long, ServerConfig> hostIdMapConfig = list.stream().collect(Collectors.toMap(ServerConfig::getServerId, Function.identity(), (f, s) -> f));
for (Server host : hosts) {
host.setConfig(hostIdMapConfig.get(host.getId()));
}
}
public void associateHostVms(Collection<Server> hosts) {
Set<Long> hostIds = hosts.stream().map(Server::getId).collect(Collectors.toSet());
Assert.notEmpty(hostIds, "资源池中没有合适的宿主机");
//统一查询虚拟机
List<CloudServer> cloudServerList = cloudServerRepository.queryProxy()
.col(CloudServer::getHostId).in(hostIds)
.col(GenericEntity::getDeleted).notEq(1)
.col(CloudServer::getIsTemplate).notEq(1)
// 只查询活动状态下的虚拟机进行计算
.col(CloudServer::getStatus).in("BUILDING", "RUNNING")
.list();
logger.info("当前所有宿主机: {},下的虚拟机信息:{}", JSON.toJSONString(hostIds), JSON.toJSONString(cloudServerList));
Map<Long, List<CloudServer>> cloudServerMap = cloudServerList.stream().collect(Collectors.groupingBy(CloudServer::getHostId));
for (Server host : hosts) {
host.setServers(cloudServerMap.get(host.getId()));
}
}
/**
*
*
* 宿dataStores
*
* @return
*/
public void associateHostDataStores(Collection<Server> hosts) {
/** cloudTowerdataStore,宿
dataStorevc宿cloudTowermock宿
**/
Map<Long, List<Server>> vendorMapHosts = hosts.stream().collect(Collectors.groupingBy(Server::getVendorId));
for (Map.Entry<Long, List<Server>> entry : vendorMapHosts.entrySet()) {
List<Server> hostList = entry.getValue();
CloudVendor vendor = hostList.get(0).getVendor();
CloudProvider provider = CloudProvider.valueOf(vendor.getType());
List<Long> hostIds = hostList.stream().map(Server::getId).collect(Collectors.toList());
switch (provider) {
// case VMWARE:
// associateVmwareHostsDataStore(hosts, vendor, hostIds);
// break;
case CLOUDTOWER:
associateCloudTowerHostsDataStore(hostList);
break;
// case ARCHEROS:
// associatArcherOsHostsDataStore(hostList);
// break;
}
}
}
private static void associateCloudTowerHostsDataStore(List<Server> hostList) {
for (Server server : hostList) {
ServerConfig config = server.getConfig();
DataStore dataStore = new DataStore();
//设置一个模拟的id,负数Id不会和数据库中的冲突
dataStore.setId(-new Random().nextLong());
dataStore.setCapacity(config.getDiskCapacity().longValue());
dataStore.setFreeSpace(config.getDiskCapacity().longValue() - config.getDiskUsed().longValue());
server.setDataStores(Arrays.asList(dataStore));
}
}
}

View File

@ -11,6 +11,7 @@ import com.bocloud.cmp.entity.enums.ResourceCategory;
import com.bocloud.cmp.model.*;
import com.bocloud.cmp.model.common.*;
import com.bocloud.cmp.model.common.OrderMessage.Operation;
import com.bocloud.cmp.vm.model.CloudTowerDisk;
import com.bocloud.cmp.vm.model.VmGenericParam;
import com.bocloud.common.encrypt.AESEncrptor;
import com.bocloud.common.encrypt.Encryptor;
@ -410,6 +411,46 @@ public class VMApplyServiceImpl implements VMApplyService {
}
}
// assignMapTarget = new HashMap<>();
List<AssignResult> assignParamListBak = new ArrayList<>();
//ct分配资源
if (provider == CloudProvider.CLOUDTOWER) {
List<AssignParam> assignParamList = new ArrayList<>();
AssignParam assignParam = param.getAssignParam();
//设置系统盘
assignParam.setDisk(assignParam.getTemplateDisk());
//处理数据盘
List<CloudTowerDisk> cloudTowerDisks = Optional.ofNullable(assignParam.getOriginalConfigs()).map(c -> c.getJSONArray("volumeModels")).map(a -> a.toJavaList(CloudTowerDisk.class)).orElse(new ArrayList<>());
//设置数据盘申请参数
List<AssignDataDiskParam> dataDiskParams = cloudTowerDisks.stream().map(AssignDataDiskParam::new).collect(Collectors.toList());
assignParam.setDataDiskParams(dataDiskParams);
assignParamList.add(assignParam);
PoolGroup poolGroup = poolGroupRepository.query(location.getPoolGroupId());
List<AssignResult> assignResultList = resSchedulerEngine.assign(poolGroup, vendor, assignParamList);
Map<String, List<AssignResult>> assignMapTarget = assignResultList.stream().collect(Collectors.groupingBy(obj -> {
String assignId = obj.getAssignId();
if (assignId == null) {
assignId = "";
}
return assignId;
}));
Assert.notEmpty(assignMapTarget, "云主机调度失败");
//如果有uuid关联的分配结果则一般为反亲和
if (assignMapTarget.containsKey(assignParam.getUuid())) {
assignParamListBak = assignMapTarget.get(assignParam.getUuid());
} else {//如果没有uuid关联的分配结果则为随机或者亲和
assignParamListBak = assignMapTarget.get("");
}
}
if (CloudProvider.VMWARE == provider) {
BocloudResult<List<JSONObject>> bocloudResult = null;
// 如果没有使用计算资源池,则默认按照随机策略分配宿主机和存储
@ -493,6 +534,7 @@ public class VMApplyServiceImpl implements VMApplyService {
}
}
logger.info("分配后的IP信息" + JSON.toJSONString(configs.getString("networkCardConfigs")));
if (provider.equals(CloudProvider.SANGFOR) && "6.8".equals(vendor.getVersion())){
//获取资源池Id
@ -519,7 +561,7 @@ public class VMApplyServiceImpl implements VMApplyService {
JSONArray networkCardConfigs1 = configs.getJSONArray("networkCardConfigs");
for (Object netWork : networkCardConfigs1){
JSONObject jsonObject = (JSONObject) netWork;
JSONArray address = jsonObject.getJSONArray("address");
JSONArray address = provider.equals(CloudProvider.CLOUDTOWER) ? jsonObject.getJSONArray("ipAddress") : jsonObject.getJSONArray("address");
Long ipPoolId = jsonObject.getLong("ipPoolId");
if (address.isEmpty()) {
BocloudResult<List<Ip>> listBocloudResult = ipService.achievePoolIps(ipPoolId, count.longValue(), null);
@ -550,7 +592,7 @@ public class VMApplyServiceImpl implements VMApplyService {
for (Object object : networkCardConfigs) {
JSONObject jsonObject = (JSONObject) object;
BocloudResult<User> userDetail = smsUserService.detail(location.getCreatorId());
newObj.put("name", jsonObject.getJSONArray("address").get(i) +"-"+ userDetail.getData().getName() +"-"+purpose);
newObj.put("name", (provider.equals(CloudProvider.CLOUDTOWER) ? jsonObject.getJSONArray("ipAddress") : jsonObject.getJSONArray("address")).get(i) + "-" + userDetail.getData().getName() + "-" + purpose);
break;
}
}
@ -603,6 +645,26 @@ public class VMApplyServiceImpl implements VMApplyService {
}
if (!ListTool.isEmpty(assignParamListBak)) {
AssignResult targetObj = assignParamListBak.get(i);
//设置宿主机,系统盘存储位置
newObj.put("storeId", targetObj.getStoreId());
newObj.put("hostId", targetObj.getHostId());
newObj.put("vdcId", targetObj.getVdcId());
//冗余一个宿主机ID,cloudTower通过serverId来控制磁盘
newObj.put("serverId", targetObj.getHostId());
newObj.put("clusterId", targetObj.getClusterId());
//这个属性创建时暂时没有找到使用的地方,后续可以考虑删除
newObj.put("dataDiskList", newObj.getString("addDiskList"));
newObj.put("diskDevices", newObj.get("volumeModels"));
newObj.put("networkCards", newObj.get("networkCardConfigs"));
// 暂时注释,解决没有数据盘问题
// newObj.remove("addDiskList");
}
if (!ListTool.isEmpty(targetObjs)) {
JSONObject targetObj = targetObjs.get(i);
if (hostId != null && hostId.longValue() > 0L) {
@ -680,6 +742,15 @@ public class VMApplyServiceImpl implements VMApplyService {
} else if (CloudProvider.SANGFOR == provider){
result = serverOperationHelper.prepareSangfor(object, param.getContext(), vendor, process, indexInSpec, size);
} else {
if (CloudProvider.CLOUDTOWER == provider) {
//ct的特殊处理
JSONArray networkCardConfigs = object.getJSONArray("networkCardConfigs");
for (Object networkCardConfig : networkCardConfigs) {
JSONObject jsonObject = (JSONObject) networkCardConfig;
jsonObject.put("ipAddress", jsonObject.getJSONArray("ipAddress").get(indexInSpec));
}
}
result = serverOperationHelper.prepare(
JSONObject.parseObject(object.toJSONString(), VmGenericParam.class), param.getContext(), vendor,
process);