package com.sobey.cmop.mvc.service.basicdata;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.sobey.cmop.mvc.comm.BaseSevcie;
import com.sobey.cmop.mvc.constant.ComputeConstant;
import com.sobey.cmop.mvc.constant.IpPoolConstant;
import com.sobey.cmop.mvc.dao.HostServerDao;
import com.sobey.cmop.mvc.dao.NicDao;
import com.sobey.cmop.mvc.dao.custom.HostServerDaoCustom;
import com.sobey.cmop.mvc.dao.custom.IpPoolDaoCustom;
import com.sobey.cmop.mvc.entity.ComputeItem;
import com.sobey.cmop.mvc.entity.HostServer;
import com.sobey.cmop.mvc.entity.IpPool;
import com.sobey.cmop.mvc.entity.Nic;
import com.sobey.cmop.mvc.entity.ServerModel;
import com.sobey.cmop.mvc.service.vm.HostTree;
import com.sobey.framework.utils.DynamicSpecifications;
import com.sobey.framework.utils.Identities;
import com.sobey.framework.utils.SearchFilter;
/**
* 宿主机/物理机管理类
*
* @author wenlp
*/
@Service
@Transactional(readOnly = true)
public class HostServerService extends BaseSevcie {
private static Logger logger = LoggerFactory.getLogger(HostServerService.class);
@Resource
private HostServerDao hostServerDao;
@Resource
private HostServerDaoCustom hostServerDaoCustom;
@Resource
private NicDao nicDao;
@Resource
private IpPoolDaoCustom ipPoolDaoCustom;
/**
* 1/0/: 模板
*/
private static final String SWITCH_FORMAT = " 1/0/";
// ========== nicDao =============/
@Transactional(readOnly = false)
public Nic saveOrUpdate(Nic nic) {
return nicDao.save(nic);
}
@Transactional(readOnly = false)
public void deleteNic(Collection<Nic> nics) {
nicDao.delete(nics);
}
/**
* 获得指定服务器的网卡列表.
*
* @param hostServerId
* @return
*/
public List<Nic> getNicByhostServerId(Integer hostServerId) {
return nicDao.findByHostServerId(hostServerId);
}
// ========== HostServer =============/
/**
* 新增,保存HostServer
*
* @param hostServer
* @return
*/
@Transactional(readOnly = false)
public HostServer saveOrUpdate(HostServer hostServer) {
return hostServerDao.save(hostServer);
}
public HostServer getHostServer(Integer id) {
return hostServerDao.findOne(id);
}
/**
* 删除HostServer和oneCMDB的相关数据,同时初始化HostServer关联的IP.
*
* @param id
* @return
*/
@Transactional(readOnly = false)
public boolean delete(Integer id) {
HostServer hostServer = this.getHostServer(id);
// 初始化IP.
comm.ipPoolService.initIpPool(hostServer.getIpAddress());
List<Nic> nics = this.getNicByhostServerId(id);
for (Nic nic : nics) {
comm.ipPoolService.initIpPool(nic.getIpAddress());
}
// 删除oneCMDB中的数据
comm.oneCmdbUtilService.deleteHostServerToOneCMDB(hostServer);
hostServerDao.delete(id);
return true;
}
/**
*
* 新增,更新HostServer
*
* <pre>
* 1.保存服务器和网卡信息.
* 2.将分配的IP状态设置为已使用状态.
* 3.同步数据至oneCMDB.
* </pre>
*
* @param hostServer
* hostServer对象
* @param serverType
* 服务器类型
* @param serverModelId
* 服务器型号
* @param rack
* 机柜位置
* @param site
* 模块位置
* @param nicSite
* 网卡位置
* @param switchs
* 交换机(alias+name)
* @param switchSite
* 交换机口
* @param mac
* mac
* @param height
* 高度
* @param locationAlias
* IDC alias
* @param ipAddress
* 服务器自身IP
* @param description
* 说明
* @return
*/
@Transactional(readOnly = false)
private boolean saveOrUpdateHostServer(HostServer hostServer, Integer serverType, Integer serverModelId,
String rack, String site, String switchs, String switchSite, String height, String locationAlias,
String ipAddress, String description, String managementMac, String[] nicSites, String[] nicMacs,
String[] nicIpAddress) {
boolean flag = false;
ServerModel serverModel = comm.serverModelService.getServerModel(serverModelId);
String[] racks = StringUtils.split(rack, "&");
String rackAlias = racks[0];
String rackName = racks[1];
/*
* DisplayName
*
* Company Model Rack-Site
*
* eg:HP DL2000 0416-1-1
*/
String displayName = serverModel.getCompany() + " " + serverModel.getName() + " " + rackName + "-" + site;
String[] switchArray = StringUtils.split(switchs, "&");
String switchAlias = switchArray[0];
/*
* 交换机插入oneCMDB中的格式化模板.最终结果为 XA041101SW 1/0/12
*
* XA041101SW:交换机名
*
* 1/0/: 模板(常量)
*
* 12:交换机位置
*/
String switchName = switchArray[1] + SWITCH_FORMAT + switchSite;
// 判断服务器是否重名.
if (this.findByDisplayName(displayName) == null || displayName.equals(hostServer.getDisplayName())) {
// 初始化修改前的IP.
comm.ipPoolService.initIpPool(hostServer.getIpAddress());
IpPool ipPool = comm.ipPoolService.findIpPoolByIpAddress(ipAddress);
hostServer.setDisplayName(displayName);
hostServer.setIpAddress(ipAddress);
hostServer.setLocationAlias(locationAlias);
hostServer.setPoolType(ipPool.getPoolType());
hostServer.setServerType(serverType);
hostServer.setHeight(height);
hostServer.setSite(site);
hostServer.setServerModel(serverModel);
hostServer.setDescription(description);
hostServer.setRack(rackName);
hostServer.setRackAlias(rackAlias);
hostServer.setSwitchAlias(switchAlias);
hostServer.setSwitchName(switchName);
hostServer.setSwitchSite(switchSite);
hostServer.setManagementMac(managementMac);
// step.2 更改IP状态为 已使用
ipPool.setStatus(IpPoolConstant.IpStatus.已使用.toInteger());
comm.ipPoolService.saveOrUpdate(ipPool);
this.saveOrUpdate(hostServer);
// 保存网卡信息
this.saveNic(hostServer, nicSites, nicMacs, nicIpAddress);
// step.3 同步oneCMDB
comm.oneCmdbUtilService.saveHostServerToOneCMDB(hostServer);
flag = true;
}
return flag;
}
/**
* 保存Nics
*
* @param hostServer
* @param nicSites
* @param nicMacs
* @param nicIpAddress
*/
@Transactional(readOnly = false)
private void saveNic(HostServer hostServer, String[] nicSites, String[] nicMacs, String[] nicIpAddress) {
List<Nic> nics = this.getNicByhostServerId(hostServer.getId());
if (!nics.isEmpty()) {
// 删除oneCMDB中网卡数据.
comm.oneCmdbUtilService.deleteServerPortToOneCMDB(hostServer);
for (Nic nic : nics) {
// 初始化修改前的IP.
comm.ipPoolService.initIpPool(nic.getIpAddress());
}
this.deleteNic(nics);
}
if (nicSites != null) {
int count = nicSites.length;
for (int i = 0; i < count; i++) {
// 更改IP状态为 已使用
IpPool ipPool = comm.ipPoolService.findIpPoolByIpAddress(nicIpAddress[i]);
ipPool.setStatus(IpPoolConstant.IpStatus.已使用.toInteger());
comm.ipPoolService.saveOrUpdate(ipPool);
String alias = "Nic" + Identities.uuid2();
Nic nic = new Nic(hostServer, nicMacs[i], nicIpAddress[i], alias, nicSites[i]);
this.saveOrUpdate(nic);
}
}
}
/**
* 新增HostServer
*
* @param serverType
* 服务器类型
* @param serverModelId
* 服务器型号
* @param rack
* 机柜位置
* @param site
* 模块位置
* @param nicSite
* 网卡位置
* @param switchs
* 交换机(alias+name)
* @param switchSite
* 交换机口
* @param mac
* mac
* @param height
* 高度
* @param locationAlias
* IDC alias
* @param ipAddress
* 服务器自身IP
* @param description
* 说明
* @return
*/
@Transactional(readOnly = false)
public boolean addHostServer(Integer serverType, Integer serverModelId, String rack, String site, String switchs,
String switchSite, String height, String locationAlias, String ipAddress, String description,
String managementMac, String[] nicSites, String[] nicMacs, String[] nicIpAddress) {
String alias = "Host" + Identities.uuid2();
HostServer hostServer = new HostServer();
hostServer.setAlias(alias);
hostServer.setCreateTime(new Date());
return this.saveOrUpdateHostServer(hostServer, serverType, serverModelId, rack, site, switchs, switchSite,
height, locationAlias, ipAddress, description, managementMac, nicSites, nicMacs, nicIpAddress);
}
/**
* 更新 hostServer
*
* @param id
* hostServerId
* @param serverType
* 服务器类型
* @param serverModelId
* 服务器型号
* @param rack
* 机柜位置
* @param site
* 模块位置
* @param nicSite
* 网卡位置
* @param switchs
* 交换机(alias+name)
* @param switchSite
* 交换机口
* @param managementMac
* 管理口Mac
* @param height
* 高度
* @param locationAlias
* IDC alias
* @param ipAddress
* 服务器自身IP
* @param description
* 说明
* @return
*/
@Transactional(readOnly = false)
public boolean updateHostServer(Integer id, Integer serverType, Integer serverModelId, String rack, String site,
String switchs, String switchSite, String height, String locationAlias, String ipAddress,
String description, String managementMac, String[] nicSites, String[] nicMacs, String[] nicIpAddress) {
HostServer hostServer = this.getHostServer(id);
return this.saveOrUpdateHostServer(hostServer, serverType, serverModelId, rack, site, switchs, switchSite,
height, locationAlias, ipAddress, description, managementMac, nicSites, nicMacs, nicIpAddress);
}
/**
* 更新HostServer挂载的实例.
*
* <pre>
* 1.根据computeId获得compute对象,并将根据实例对象的资源类型computeType更新serverAlias或hostServerAlias.
* 2.根据compute对象里的innerIp获得IpPool对象,并将由serverAlias获得的hostServer对象更新至IpPool中.
* </pre>
*
* @param computeIds
* 实例ID数组
* @param serverAlias
* hostServer(宿主机 & 物理机) Alias 数组
*/
@Transactional(readOnly = false)
public void updateHostServerTree(String[] computeIds, String[] serverAlias) {
if (computeIds != null) {
for (int i = 0; i < serverAlias.length; i++) {
// step.1
ComputeItem computeItem = comm.computeService.getComputeItem(Integer.valueOf(computeIds[i]));
if (ComputeConstant.ComputeType.PCS.toInteger().equals(computeItem.getComputeType())) {
computeItem.setServerAlias(serverAlias[i]);
} else {
computeItem.setHostServerAlias(serverAlias[i]);
}
comm.computeService.saveOrUpdate(computeItem);
// step.2
IpPool ipPool = comm.ipPoolService.findIpPoolByIpAddress(computeItem.getInnerIp());
ipPool.setHostServer(this.findByAlias(serverAlias[i]));
comm.ipPoolService.saveOrUpdate(ipPool);
}
}
}
@Transactional(readOnly = false)
public boolean saveHostServer(HostServer hostServer) {
if (hostServer.getId() != null) { // 更新新旧IP状态
HostServer oldHostServer = getHostServer(hostServer.getId());
if (!oldHostServer.getIpAddress().equals(hostServer.getIpAddress())) {
// 更新旧IP状态:未使用
comm.ipPoolService.updateIpPoolByIpAddress(oldHostServer.getIpAddress(),
IpPoolConstant.IpStatus.未使用.toInteger(), null);
// 判断新IP是否存在
if (comm.ipPoolService.findIpPoolByIpAddress(hostServer.getIpAddress()) != null) { // 存在则更新IP状态:已使用
comm.ipPoolService.updateIpPoolByIpAddress(hostServer.getIpAddress(),
IpPoolConstant.IpStatus.已使用.toInteger(), null);
} else { // 创建新的IP
comm.ipPoolService.saveIpPool(hostServer.getIpAddress(), IpPoolConstant.PoolType.私网IP池.toInteger(),
IpPoolConstant.IpStatus.已使用.toInteger(), comm.vlanService.getVlan(1), null); // 默认西安虚拟机内网VLAN
}
}
} else { // 创建新的IP
comm.ipPoolService.saveIpPool(hostServer.getIpAddress(), IpPoolConstant.PoolType.私网IP池.toInteger(),
IpPoolConstant.IpStatus.已使用.toInteger(), comm.vlanService.getVlan(1), null); // 默认西安虚拟机内网VLAN
}
// 保存服务器
hostServerDao.save(hostServer);
return true;
}
public Page<HostServer> getHostServerPageable(Map<String, Object> searchParams, int pageNumber, int pageSize) {
PageRequest pageRequest = buildPageRequest(pageNumber, pageSize);
Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
Specification<HostServer> spec = DynamicSpecifications.bySearchFilter(filters.values(), HostServer.class);
return hostServerDao.findAll(spec, pageRequest);
}
/**
* 获得指定宿主机Host下的ECS.
*
* @param id
* @return
*/
@SuppressWarnings("rawtypes")
public List<ComputeItem> getEcsByHost(Integer id) {
List<ComputeItem> computeItems = new ArrayList<ComputeItem>();
List list = hostServerDaoCustom.getEcsByHost(id);
for (int i = 0; i < list.size(); i++) {
Object[] object = (Object[]) list.get(i);
computeItems.add(comm.basicUnitService.wrapComputeItem(object));
}
return computeItems;
}
/**
* 宿主机及其虚拟机关系同步
*
* @return
*/
@Transactional(readOnly = false)
public String syn() {
try {
// 1. 同步所有宿主机及其虚拟机
List list = HostTree.call();
// 2. 更新宿主机对应IP状态及其关联虚拟机IP状态为:未使用
int updateCount = ipPoolDaoCustom.updateIpPoolByStatus(IpPoolConstant.IpStatus.未使用.toInteger());
// 3. 删除所有宿主机
// int deleteCount = hostServerDaoCustom.deleteHostByServerType(1);
List<String> hostList;
List<Map> hostListMap;
int hostCount = 0;
int vmCount = 0;
String ipAddress;
List hostServerList;
HostServer hostServer;
for (int k = 0; k < list.size(); k++) {
hostList = (List<String>) ((List) list.get(k)).get(0);
hostListMap = (List<Map>) ((List) list.get(k)).get(1);
for (int i = 0; i < hostList.size(); i++) {
ipAddress = hostList.get(i);
hostCount++;
// 4. 写入新的宿主机
hostServerList = hostServerDao.findByIpAddress(ipAddress);
if (hostServerList != null && hostServerList.size() > 0) {
logger.info("已存在的宿主机:" + ipAddress + ",hostServerList.size=" + hostServerList.size());
hostServer = (HostServer) hostServerList.get(0);
} else {
hostServer = new HostServer(1, IpPoolConstant.PoolType.私网IP池.toInteger(), hostList.get(i),
new Date()); // 名称默认为IP;IP池默认为私网IP池
hostServer.setAlias(Identities.uuid2());
hostServer.setIpAddress(ipAddress);
hostServer.setLocationAlias(comm.locationService.getLocation(2).getAlias()); // IDC别名默认西安IDC
hostServerDao.save(hostServer);
}
// 5. 更新宿主机对应IP状态为:已使用
if (comm.ipPoolService.findIpPoolByIpAddress(ipAddress) != null) {
logger.info("已存在的宿主机IP:" + ipAddress);
comm.ipPoolService.updateIpPoolByIpAddress(ipAddress, IpPoolConstant.IpStatus.已使用.toInteger(),
null);
} else {
comm.ipPoolService.saveIpPool(ipAddress, IpPoolConstant.PoolType.私网IP池.toInteger(),
IpPoolConstant.IpStatus.已使用.toInteger(), comm.vlanService.getVlan(1), null); // 默认西安虚拟机内网VLAN
}
// 6. 更新其关联虚拟机及其IP状态为:已使用
Map host = (Map) hostListMap.get(i);
List ecsList = (List) host.get(hostList.get(i));
for (int j = 0; j < ecsList.size(); j++) {
ipAddress = (String) ecsList.get(j);
vmCount++;
if (comm.ipPoolService.findIpPoolByIpAddress(ipAddress) != null) {
logger.info("已存在的虚拟机IP:" + ipAddress);
comm.ipPoolService.updateIpPoolByIpAddress(ipAddress,
IpPoolConstant.IpStatus.已使用.toInteger(), hostServer);
} else {
comm.ipPoolService.saveIpPool(ipAddress, IpPoolConstant.PoolType.私网IP池.toInteger(),
IpPoolConstant.IpStatus.已使用.toInteger(), comm.vlanService.getVlan(1), hostServer); // 默认西安虚拟机内网VLAN
}
}
}
}
return "true-" + hostCount + "-" + vmCount;
} catch (Exception e) {
e.printStackTrace();
return "false-0-0";
}
}
/**
* 导出数据到Excel
*
* @return
*/
public boolean export() {
Iterable<HostServer> hosts = hostServerDao.findAll();
PoiUtil.writeExcel("D:/Host_Vm.xls", "宿主机及其虚拟机关系表", new String[] { "宿主机IP", "DisplayName", "虚拟机IP" }, hosts);
return true;
}
/**
* 写入数据到OneCMDB
*
* @return
*/
@Transactional(readOnly = false)
public boolean write() {
Iterable<HostServer> hosts = hostServerDao.findAll();
PoiUtil.writeExcel("D:/Host_Vm.xls", "宿主机及其虚拟机关系表", new String[] { "宿主机IP", "DisplayName", "虚拟机IP" }, hosts);
return true;
}
public List<HostServer> findByServerType(int serverType) {
return hostServerDao.findByServerType(serverType);
}
public HostServer findByAlias(String alias) {
return hostServerDao.findByAlias(alias);
}
public HostServer findByDisplayName(String displayName) {
return hostServerDao.findByDisplayName(displayName);
}
}