diff --git a/dme-vcenter-plugin/plugin-package.xml b/dme-vcenter-plugin/plugin-package.xml index d6952cc71..8eeec14d7 100644 --- a/dme-vcenter-plugin/plugin-package.xml +++ b/dme-vcenter-plugin/plugin-package.xml @@ -9,7 +9,7 @@ type: keep "html" for this plugin to be deployed in the vSphere HTML client. name: short name displayed in the Administration < Client plugins view --> - diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/constant/DmeConstants.java b/dmestore-service/src/main/java/com/huawei/dmestore/constant/DmeConstants.java index 5b6b6b7c2..99b4608d0 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/constant/DmeConstants.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/constant/DmeConstants.java @@ -14,10 +14,13 @@ public class DmeConstants { * POST * estimate connectivity of host or hostgroup on dme * old - * public static final String DME_ESTIMATE_CONNECTIVITY = "/rest/vmmgmt/v1/connectivity/host-storage"; */ - //public static final String DME_ESTIMATE_CONNECTIVITY = "/rest/vmmgmt/v1/connectivity/host-storage"; public static final String DME_ESTIMATE_CONNECTIVITY = "/rest/hostmgmt/v1/connectivity/host-and-storage"; + /** + * query oriented volume + * /rest/blockservice/v1/volumes/{volume_id} + */ + public static final String DME_QUERY_ONE_VOLUME = "/rest/blockservice/v1/volumes/{volume_id}"; /** * nfs share detail **/ @@ -158,6 +161,12 @@ public class DmeConstants { **/ public static final String MOUNT_VOLUME_TO_HOSTGROUP_URL = "/rest/blockservice/v1/volumes/hostgroup-mapping"; + /** + * hostgroup mapping view query + * post + **/ + public static final String QUERY_HOSTGROUP_MAPPING_VIEW_URL = "/rest/blockservice/v1/volumes/mapping-view/query"; + /** * volume expand **/ diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/filter/CorsFilter.java b/dmestore-service/src/main/java/com/huawei/dmestore/filter/CorsFilter.java index 87f9ed40f..ee68b907d 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/filter/CorsFilter.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/filter/CorsFilter.java @@ -30,6 +30,7 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha throws IOException, ServletException { HttpServletResponse res = (HttpServletResponse) response; res.addHeader("Access-Control-Allow-Credentials", "true"); + //res.addHeader("Access-Control-Allow-Origin", "http://localhost:4200"); res.addHeader("Access-Control-Allow-Origin", "*"); res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT"); res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN"); diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/model/Attachment.java b/dmestore-service/src/main/java/com/huawei/dmestore/model/Attachment.java new file mode 100644 index 000000000..fe1a43cf0 --- /dev/null +++ b/dmestore-service/src/main/java/com/huawei/dmestore/model/Attachment.java @@ -0,0 +1,69 @@ +package com.huawei.dmestore.model; + +import java.util.Date; + +/** + * @author yc + * @Title: + * @Description: + * @date 2021/5/2518:03 + */ +public class Attachment { + private String id; + private String volumeId; + private String hostId; + private String attachedAt; + private String attachedHostGroup; + private Date attachedAtDate; + + public Attachment() { + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getVolumeId() { + return volumeId; + } + + public void setVolumeId(String volumeId) { + this.volumeId = volumeId; + } + + public String getHostId() { + return hostId; + } + + public void setHostId(String hostId) { + this.hostId = hostId; + } + + public String getAttachedAt() { + return attachedAt; + } + + public void setAttachedAt(String attachedAt) { + this.attachedAt = attachedAt; + } + + public String getAttachedHostGroup() { + return attachedHostGroup; + } + + public void setAttachedHostGroup(String attachedHostGroup) { + this.attachedHostGroup = attachedHostGroup; + } + + public Date getAttachedAtDate() { + return attachedAtDate; + } + + public void setAttachedAtDate(Date attachedAtDate) { + this.attachedAtDate = attachedAtDate; + } +} diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/model/ClusterTree.java b/dmestore-service/src/main/java/com/huawei/dmestore/model/ClusterTree.java new file mode 100644 index 000000000..fbc5d9fb3 --- /dev/null +++ b/dmestore-service/src/main/java/com/huawei/dmestore/model/ClusterTree.java @@ -0,0 +1,69 @@ +package com.huawei.dmestore.model; + +import java.io.Serializable; +import java.util.List; + +/** + * @author yc + * @Title: ClusterTree + * @Description: be used encapsulation cluster tree + * @date 2021/5/1114:15 + */ +public class ClusterTree implements Serializable { + private static final long serialVersionUID = 6756705875820791027L; + private String clusterId; + private String clusterName; + private boolean flag = true; + private List children; + + public ClusterTree(String clusterId, String clusterName, List children) { + this.clusterId = clusterId; + this.clusterName = clusterName; + this.children = children; + } + + public ClusterTree() { + + } + + public String getClusterId() { + return clusterId; + } + + public void setClusterId(String clusterId) { + this.clusterId = clusterId; + } + + public String getClusterName() { + return clusterName; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + public boolean isFlag() { + return flag; + } + + public void setFlag(boolean flag) { + this.flag = flag; + } + + @Override + public String toString() { + return "ClusterTree{" + + "clusterId='" + clusterId + '\'' + + ", clusterName='" + clusterName + '\'' + + ", children=" + children + + '}'; + } +} diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/model/CreateVmfsResponse.java b/dmestore-service/src/main/java/com/huawei/dmestore/model/CreateVmfsResponse.java new file mode 100644 index 000000000..904097269 --- /dev/null +++ b/dmestore-service/src/main/java/com/huawei/dmestore/model/CreateVmfsResponse.java @@ -0,0 +1,96 @@ +package com.huawei.dmestore.model; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +/** + * @author yc + * @Title: + * @Description: + * @date 2021/5/2810:41 + */ +public class CreateVmfsResponse implements Serializable { + private static final long serialVersionUID = 8718802610431878776L; + + private int successNo; + private int failNo; + private List connectionResult ; + private String descriptionEN; + private String descriptionCN; + + public CreateVmfsResponse() { + } + + @Override + public String toString() { + return "CreateVmfsResponse{" + + "successNo=" + successNo + + ", failNo=" + failNo + + ", connectionResult=" + connectionResult + + '}'; + } + + public CreateVmfsResponse(int successNo) { + this.successNo = successNo; + } + + public CreateVmfsResponse(int successNo, int failNo) { + this.successNo = successNo; + this.failNo = failNo; + } + + public CreateVmfsResponse(int successNo, int failNo, List connectionResult) { + this.successNo = successNo; + this.failNo = failNo; + this.connectionResult = connectionResult; + } + + public int getSuccessNo() { + return successNo; + } + + public void setSuccessNo(int successNo) { + this.successNo = successNo; + } + + public int getFailNo() { + return failNo; + } + + public void setFailNo(int failNo) { + this.failNo = failNo; + } + + public List getConnectionResult() { + return connectionResult; + } + + public void setConnectionResult(List connectionResult) { + this.connectionResult = connectionResult; + } + + public String getDescriptionEN() { + return descriptionEN; + } + + public void setDescriptionEN(String descriptionEN) { + this.descriptionEN = descriptionEN; + } + + public String getDescriptionCN() { + return descriptionCN; + } + + public void setDescriptionCN(String descriptionCN) { + this.descriptionCN = descriptionCN; + } + + public CreateVmfsResponse(int successNo, int failNo, List connectionResult, String descriptionEN, String descriptionCN) { + this.successNo = successNo; + this.failNo = failNo; + this.connectionResult = connectionResult; + this.descriptionEN = descriptionEN; + this.descriptionCN = descriptionCN; + } +} diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/model/HostGroupAndClusterConsistency.java b/dmestore-service/src/main/java/com/huawei/dmestore/model/HostGroupAndClusterConsistency.java new file mode 100644 index 000000000..c9ec8e48d --- /dev/null +++ b/dmestore-service/src/main/java/com/huawei/dmestore/model/HostGroupAndClusterConsistency.java @@ -0,0 +1,43 @@ +package com.huawei.dmestore.model; + +/** + * @author yc + * @Title: + * @Description: + * @date 2021/5/3111:23 + */ +public class HostGroupAndClusterConsistency { + private boolean consistency; //true 一致; false 不一致 + private String hostGroupId; //主机组id + + public HostGroupAndClusterConsistency() { } + + public HostGroupAndClusterConsistency(boolean consistency) { + this.consistency = consistency; + } + + public HostGroupAndClusterConsistency(String hostGroupId) { + this.hostGroupId = hostGroupId; + } + + public boolean isConsistency() { + return consistency; + } + + public void setConsistency(boolean consistency) { + this.consistency = consistency; + } + + public String getHostGroupId() { + return hostGroupId; + } + + public void setHostGroupId(String hostGroupId) { + this.hostGroupId = hostGroupId; + } + + public HostGroupAndClusterConsistency(boolean consistency, String hostGroupId) { + this.consistency = consistency; + this.hostGroupId = hostGroupId; + } +} diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/model/TaskDetailInfoNew.java b/dmestore-service/src/main/java/com/huawei/dmestore/model/TaskDetailInfoNew.java new file mode 100644 index 000000000..5bc838d17 --- /dev/null +++ b/dmestore-service/src/main/java/com/huawei/dmestore/model/TaskDetailInfoNew.java @@ -0,0 +1,159 @@ +package com.huawei.dmestore.model; + +import java.util.List; + +/** + * @author yc + * @Title: + * @Description: + * @date 2021/5/2114:10 + */ +public class TaskDetailInfoNew { + private String id; + private String nameEn; + private String nameCn; + private String description; + private String parentId; + private Integer seqNo; + private Integer status; + private Integer progress; + private String ownerName; + private String ownerId; + private long createTime; + private long startTime; + private long endTime; + private String detailEn; + private String detailCn; + private List resources; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getNameEn() { + return nameEn; + } + + public void setNameEn(String nameEn) { + this.nameEn = nameEn; + } + + public String getNameCn() { + return nameCn; + } + + public void setNameCn(String nameCn) { + this.nameCn = nameCn; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getParentId() { + return parentId; + } + + public void setParentId(String parentId) { + this.parentId = parentId; + } + + public Integer getSeqNo() { + return seqNo; + } + + public void setSeqNo(Integer seqNo) { + this.seqNo = seqNo; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Integer getProgress() { + return progress; + } + + public void setProgress(Integer progress) { + this.progress = progress; + } + + public String getOwnerName() { + return ownerName; + } + + public void setOwnerName(String ownerName) { + this.ownerName = ownerName; + } + + public String getOwnerId() { + return ownerId; + } + + public void setOwnerId(String ownerId) { + this.ownerId = ownerId; + } + + public long getCreateTime() { + return createTime; + } + + public void setCreateTime(long createTime) { + this.createTime = createTime; + } + + public long getStartTime() { + return startTime; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } + + public long getEndTime() { + return endTime; + } + + public void setEndTime(long endTime) { + this.endTime = endTime; + } + + public String getDetailEn() { + return detailEn; + } + + public void setDetailEn(String detailEn) { + this.detailEn = detailEn; + } + + public String getDetailCn() { + return detailCn; + } + + public void setDetailCn(String detailCn) { + this.detailCn = detailCn; + } + + public List getResources() { + return resources; + } + + public void setResources(List resources) { + this.resources = resources; + } + + public TaskDetailInfoNew() { + } +} diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/model/TasksResultObject.java b/dmestore-service/src/main/java/com/huawei/dmestore/model/TasksResultObject.java new file mode 100644 index 000000000..69ecad71c --- /dev/null +++ b/dmestore-service/src/main/java/com/huawei/dmestore/model/TasksResultObject.java @@ -0,0 +1,68 @@ +package com.huawei.dmestore.model; + +/** + * @author yc + * @Title: + * @Description: + * @date 2021/5/2110:42 + */ +public class TasksResultObject { + //为true表示全部成功,为false表示部分成功或未成功 + private boolean status; + //成功的数量 + private long successNos; + //失败的数量 + private long failNos; + + private int totalSize; + + private String description; + + public TasksResultObject() { + + } + + public boolean isStatus() { + return status; + } + + public void setStatus(boolean status) { + this.status = status; + } + + public long getSuccessNos() { + return successNos; + } + + public void setSuccessNos(long successNos) { + this.successNos = successNos; + } + + public long getFailNos() { + return failNos; + } + + public void setFailNos(long failNos) { + this.failNos = failNos; + } + + public TasksResultObject(boolean status) { + this.status = status; + } + + public int getTotalSize() { + return totalSize; + } + + public void setTotalSize(int totalSize) { + this.totalSize = totalSize; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/mvc/BaseController.java b/dmestore-service/src/main/java/com/huawei/dmestore/mvc/BaseController.java index d064b8047..7c48bdad2 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/mvc/BaseController.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/mvc/BaseController.java @@ -37,6 +37,8 @@ public class BaseController { protected static final String CODE_SUCCESS = "200"; + protected static final String CODE_PARTIALSUCCESS = "206"; + protected static final String CODE_ALL_FAILURE = "-100001"; protected static final String CODE_NOTALL_FAILURE = "-100000"; @@ -240,7 +242,19 @@ protected ResponseBodyBean success(Object data, String description) { bodyBean.setDescription(description); return bodyBean; } - + /** + * success + * + * @param data data + * @param description description + * @return ResponseBodyBean + */ + protected ResponseBodyBean partialSuccess(Object data, String description) { + ResponseBodyBean bodyBean = new ResponseBodyBean(CODE_PARTIALSUCCESS, null, null); + bodyBean.setData(data); + bodyBean.setDescription(description); + return bodyBean; + } /** * failure * diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/mvc/ServiceLevelController.java b/dmestore-service/src/main/java/com/huawei/dmestore/mvc/ServiceLevelController.java index 57e60076d..53c6993df 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/mvc/ServiceLevelController.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/mvc/ServiceLevelController.java @@ -50,6 +50,21 @@ public ResponseBodyBean listServiceLevel(@RequestBody Map params } } + /** + * listServiceLevel + * + * @param dataStoreId dataStoreId + * @return ResponseBodyBean + */ + @RequestMapping(value = "/listservicelevelByVmfs", method = RequestMethod.GET) + public ResponseBodyBean listServiceLevelByVmfs(@RequestParam String dataStoreId) { + try { + return success(serviceLevelService.listServiceLevelByVmfs(dataStoreId)); + } catch (DmeException e) { + return failure(e.getMessage()); + } + } + /** * listStoragePoolsByServiceLevelId * diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/mvc/VmfsAccessController.java b/dmestore-service/src/main/java/com/huawei/dmestore/mvc/VmfsAccessController.java index 2a8eedec5..244cb5fe9 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/mvc/VmfsAccessController.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/mvc/VmfsAccessController.java @@ -2,15 +2,14 @@ import com.huawei.dmestore.constant.DmeConstants; import com.huawei.dmestore.exception.DmeException; -import com.huawei.dmestore.model.ResponseBodyBean; -import com.huawei.dmestore.model.VmfsDataInfo; -import com.huawei.dmestore.model.VmfsDatastoreVolumeDetail; +import com.huawei.dmestore.model.*; import com.huawei.dmestore.services.VmfsAccessService; import com.google.gson.Gson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; @@ -143,7 +142,6 @@ public ResponseBodyBean unmountVmfs(@RequestBody Map params) { vmfsAccessService.unmountVmfs(params); return success(null, "unmount vmfs success"); } catch (DmeException e) { - LOG.error("unmount vmfs failure:", e); failureStr = "unmount vmfs failure:" + e.getMessage(); } return failure(failureStr); @@ -268,4 +266,108 @@ public ResponseBodyBean queryVmfs(@RequestParam("dataStoreObjectId") String data public ResponseBodyBean queryDatastoreByName(@RequestParam("name") String name) { return success(vmfsAccessService.queryDatastoreByName(name)); } + + /** + * createVmfs + * + * @param params params + * @return ResponseBodyBean + */ + @RequestMapping(value = "/createvmfsnew", method = RequestMethod.POST) + public ResponseBodyBean createvmfsNew(@RequestBody Map params) { + LOG.info("accessvmfs/createvmfsnew=={}", gson.toJson(params)); + String failureStr = ""; + try { + CreateVmfsResponse result = vmfsAccessService.createVmfsNew(params); + if (result.getSuccessNo() == 0) { + return failure("create vmfs failure!",result); + }else if (result.getFailNo() != 0 || !CollectionUtils.isEmpty(result.getConnectionResult())){ + return partialSuccess(result,"create vmfs partial success!"); + }else { + return success(result, "create vmfs success"); + } + } catch (DmeException e) { + failureStr = "create vmfs failure:" + e.getMessage(); + } + return failure(failureStr); + } + + /** + * mountVmfs + * + * @param params params + * @return ResponseBodyBean + */ + @RequestMapping(value = "/mountvmfsnew", method = RequestMethod.POST) + @ResponseBody + public ResponseBodyBean mountVmfsNew(@RequestBody Map params) { + LOG.info("accessvmfs/mountvmfs=={}", gson.toJson(params)); + String failureStr = ""; + try { + List> list = vmfsAccessService.mountVmfsNew(params); + if (!CollectionUtils.isEmpty(list)) { + return failure(DmeConstants.CODE_CONNECTIVITY_FAILURE, + "mount vmfs failure,connectivity of host or hostgroup on dme error!", list); + } + return success(null, "Mount vmfs success"); + } catch (DmeException e) { + LOG.error("mount vmfs failure:", e); + failureStr = "mount vmfs failure:" + e.getMessage(); + } + return failure(failureStr); + } + + /** + * @Description: 卸载页面以树的方式展示可卸载的主机和集群(以过滤集群下未挂载的主机) + * @Param @param null + * @return @return + * @throws + * @author yc + * @Date 2021/6/8 15:17 + */ + @RequestMapping(value = "/getMountedHostGroupsAndHostReturnTree/{storageId}", method = RequestMethod.GET) + public ResponseBodyBean getHostGroupsByStorageIdNew(@PathVariable(value = "storageId") String storageId) { + try { + List hosts = vmfsAccessService.getMountedHostGroupsAndHostReturnTree(storageId); + return success(hosts); + } catch (Exception e) { + return failure(e.getMessage()); + } + } + + /** + * unmountVmfs + * + * @param params params + * @return ResponseBodyBean + */ + /*@RequestMapping(value = "/ummountvmfsnew", method = RequestMethod.POST) + public ResponseBodyBean unmountVmfsNew(@RequestBody Map params) { + LOG.info("accessvmfs/unmountvmfs=={}", gson.toJson(params)); + String failureStr = ""; + try { + // vmfsAccessService.unmountVmfsNew(params); + return success(null, "unmount vmfs success"); + } catch (DmeException e) { + LOG.error("unmount vmfs failure:", e); + failureStr = "unmount vmfs failure:" + e.getMessage(); + } + return failure(failureStr); + }*/ + /** + * queryCreationMethodByDatastore 查询存储的创建方式 + * + * @param dataStoreObjectId + * @return ResponseBodyBean + */ + @GetMapping("/queryCreationMethodByDatastore") + public ResponseBodyBean queryCreationMethodByDatastore(@RequestParam("dataStoreObjectId") String dataStoreObjectId) { + try { + String createmethod = vmfsAccessService.queryCreationMethodByDatastore(dataStoreObjectId); + return success(createmethod); + } catch (DmeException e) { + return failure(e.getMessage()); + } + } + } diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/mvc/VmwareAccessController.java b/dmestore-service/src/main/java/com/huawei/dmestore/mvc/VmwareAccessController.java index df96a3f7b..4fbe84aaf 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/mvc/VmwareAccessController.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/mvc/VmwareAccessController.java @@ -2,6 +2,7 @@ import com.huawei.dmestore.exception.DmeException; import com.huawei.dmestore.exception.DmeSqlException; +import com.huawei.dmestore.model.ClusterTree; import com.huawei.dmestore.model.ResponseBodyBean; import com.huawei.dmestore.services.VmwareAccessService; @@ -230,4 +231,60 @@ public ResponseBodyBean getRelationByObjId(@RequestParam("datastoreObjectId") St return failure("get dme volume by datastore failed!" + e.toString()); } } + /** + * Access clusters + * + * @return ResponseBodyBean + */ + @RequestMapping(value = "/listclusters", method = RequestMethod.GET) + public ResponseBodyBean listclustersReturnTree() { + String failureStr = ""; + try { + List lists = vmwareAccessService.listclustersReturnTree(); + return success(lists); + } catch (DmeException e) { + failureStr = "list vmware cluster failure:" + e.toString(); + } + return failure(failureStr); + } + + /** + * @Description: 挂载vmfs,以树的方式展示可挂载的主机和集群 + * @Param @param null + * @return @return + * @throws + * @author yc + * @Date 2021/6/7 17:29 + */ + @RequestMapping(value = "/getClustersAndHostsByDsobjectIdReturnTree", method = RequestMethod.GET) + public ResponseBodyBean getClustersByDsObjectIdNew(@RequestParam("dataStoreObjectId") String dataStoreObjectId) { + String failureStr = ""; + try { + List lists = vmwareAccessService.getClustersAndHostsByDsObjectIdNew(dataStoreObjectId); + return success(lists); + } catch (DmeException e) { + LOG.error("getClustersByDsObjectId vmware host failure:", e); + failureStr = e.getMessage(); + } + return failure(failureStr); + } + /** + * @Description: 创建vmfs,以树的方式展示可用的主机和集群 + * @Param @param null + * @return @return + * @throws + * @author yc + * @Date 2021/6/7 17:29 + */ + @RequestMapping(value = "/listHostsAndClusterReturnTree", method = RequestMethod.GET) + public ResponseBodyBean listIndependenceHosts() { + String failureStr = ""; + try { + return success(vmwareAccessService.listHostsAndClusterReturnTree()); + } catch (DmeException e) { + LOG.error("list vmware host failure:", e); + failureStr = "list vmware host failure:" + e.toString(); + } + return failure(failureStr); + } } diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/services/DmeAccessServiceImpl.java b/dmestore-service/src/main/java/com/huawei/dmestore/services/DmeAccessServiceImpl.java index b31e555c2..0bec5bc19 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/services/DmeAccessServiceImpl.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/services/DmeAccessServiceImpl.java @@ -550,7 +550,7 @@ public List> getDmeHostGroups(String hostGroupName) throws D map.put(ID_FIELD, ToolUtils.jsonToStr(object.get(ID_FIELD))); // 主机名称 map.put(NAME_FIELD, ToolUtils.jsonToStr(object.get(NAME_FIELD))); - map.put(HOST_COUNT, ToolUtils.jsonToInt(object.get(IP_FIELD), 0)); + map.put(HOST_COUNT, ToolUtils.jsonToInt(object.get(HOST_COUNT), 0)); map.put("source_type", ToolUtils.jsonToStr(object.get("source_type"))); map.put(MANAGED_STATUS_FIELD, ToolUtils.jsonToStr(object.get(MANAGED_STATUS_FIELD))); map.put(PROJECT_ID_FIELD, ToolUtils.jsonToStr(object.get(PROJECT_ID_FIELD))); @@ -627,6 +627,8 @@ public Map createHostGroup(Map params) throws Dm hostgroupmap.put(ID_FIELD, ToolUtils.jsonToStr(jsonObject.get(ID_FIELD))); hostgroupmap.put(NAME_FIELD, ToolUtils.jsonToStr(jsonObject.get(NAME_FIELD))); } + }else { + throw new DmeException("create hostgroup error,the DME return"+responseEntity); } } } catch (DmeException e) { diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/services/DmeStorageServiceImpl.java b/dmestore-service/src/main/java/com/huawei/dmestore/services/DmeStorageServiceImpl.java index 8a50d3abe..d146cc9a9 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/services/DmeStorageServiceImpl.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/services/DmeStorageServiceImpl.java @@ -368,30 +368,30 @@ public String getStorageByServiceLevelId(String serviceLevelId) throws DmeExcept String params = ToolUtils.getRequsetParams("nativeId", serviceLevelId, false, true); ResponseEntity responseEntity = dmeAccessService.accessByJson(url, HttpMethod.GET, params); int code = responseEntity.getStatusCodeValue(); - if (code != HttpStatus.OK.value()) { + JsonArray objList = gson.fromJson(responseEntity.getBody(), JsonObject.class).getAsJsonArray(OBJ_LIST); + if (code != HttpStatus.OK.value() || null == objList || objList.size() ==0) { return null; } - JsonArray objList = gson.fromJson(responseEntity.getBody(), JsonObject.class).getAsJsonArray(OBJ_LIST); String resId = objList.get(0).getAsJsonObject().get(RES_ID).getAsString(); String relationName = "M_DjTierContainsStoragePool"; url = DmeConstants.LIST_RELATION_URL.replace("{relationName}", relationName) + CONDITION; params = ToolUtils.getRequsetParams("source_Instance_Id", resId, false, false); responseEntity = dmeAccessService.accessByJson(url, HttpMethod.GET, params); code = responseEntity.getStatusCodeValue(); - if (code != HttpStatus.OK.value()) { + objList = gson.fromJson(responseEntity.getBody(), JsonObject.class).getAsJsonArray(OBJ_LIST); + if (code != HttpStatus.OK.value() || null == objList || objList.size() ==0) { return null; } - objList = gson.fromJson(responseEntity.getBody(), JsonObject.class).getAsJsonArray(OBJ_LIST); String poolId = objList.get(0).getAsJsonObject().get("target_Instance_Id").getAsString(); className = "SYS_StoragePool"; url = String.format(DmeConstants.DME_RESOURCE_INSTANCE_LIST, className) + CONDITION; params = ToolUtils.getRequsetParams("resId", poolId, true, true); responseEntity = dmeAccessService.accessByJson(url, HttpMethod.GET, params); code = responseEntity.getStatusCodeValue(); - if (code != HttpStatus.OK.value()) { + objList = gson.fromJson(responseEntity.getBody(), JsonObject.class).getAsJsonArray(OBJ_LIST); + if (code != HttpStatus.OK.value() || null == objList || objList.size() ==0) { return null; } - objList = gson.fromJson(responseEntity.getBody(), JsonObject.class).getAsJsonArray(OBJ_LIST); String storageDeviceId = objList.get(0).getAsJsonObject().get("storageDeviceId").getAsString(); url = DmeConstants.API_STORAGES; responseEntity = dmeAccessService.access(url, HttpMethod.GET, null); diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/services/ServiceLevelService.java b/dmestore-service/src/main/java/com/huawei/dmestore/services/ServiceLevelService.java index 3eb71a3c8..7d2de98e0 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/services/ServiceLevelService.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/services/ServiceLevelService.java @@ -18,6 +18,8 @@ public interface ServiceLevelService { List listServiceLevel(Map params) throws DmeException; + List listServiceLevelByVmfs(String dataStoreId) throws DmeException; + List getStoragePoolInfosByServiceLevelId(String serviceLevelId) throws DmeException; List getVolumeInfosByServiceLevelId(String serviceLevelId) throws DmeException; diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/services/ServiceLevelServiceImpl.java b/dmestore-service/src/main/java/com/huawei/dmestore/services/ServiceLevelServiceImpl.java index 05f7e4f22..3467c04d3 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/services/ServiceLevelServiceImpl.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/services/ServiceLevelServiceImpl.java @@ -39,6 +39,10 @@ public class ServiceLevelServiceImpl implements ServiceLevelService { private static final String CODE_503 = "503"; + private static final String VOLUME_ID = "volume_id"; + + private static final String HOST_ID = "host_id"; + private DmeAccessService dmeAccessService; private DmeRelationInstanceService dmeRelationInstanceService; @@ -130,6 +134,93 @@ public List listServiceLevel(Map params) thr return slis; } + @Override + public List listServiceLevelByVmfs(String datastoreId) throws DmeException { + // 通过storeobjId 查volumeId + DmeVmwareRelation dvr = dmeVmwareRalationDao.getDmeVmwareRelationByDsId(datastoreId); + if (dvr == null) { + log.error("query service Level error, query dme vmware ralation table is error!{}", datastoreId); + throw new DmeException("query service Level error, query dme vmware ralation table is error!{}",datastoreId); + } + + String volumeId = dvr.getVolumeId(); + if (StringUtils.isEmpty(volumeId)) { + log.error("query service Level error, volumeId is NULL!{}", datastoreId); + throw new DmeException("query service Level error, volumeId is NULL!{}",datastoreId); + } + + Volume volume = findOrientedVolumeMapping(volumeId); + // 通过poolrawId和storageId查询存储池、 + StoragePool pool = new StoragePool(); + List pools = dmeStorageService.getStoragePools(volume.getStorageId(), "all"); + for (StoragePool storagePool : pools) { + String poolId = storagePool.getPoolId(); + if (poolId.equalsIgnoreCase(volume.getPoolRawId())) { + pool = storagePool; + break; + } + } + + List serviceLevels = listServiceLevel(null); + // 通过volumeid查存储池或者所属服务等级Id + if (CollectionUtils.isEmpty(serviceLevels)) { + log.error("query service Level error, service level list is NULL!"); + throw new DmeException("query service Level error, service level list is NULL!"); + } + + List serverLevels = new ArrayList<>(); + List storagePools = new ArrayList<>(); + for (SimpleServiceLevel serviceLevel : serviceLevels) { + String serviceLevelId = serviceLevel.getId(); + if (!StringUtils.isEmpty(serviceLevelId)) { + storagePools = getStoragePoolInfosByServiceLevelId(serviceLevelId); + } + if (!CollectionUtils.isEmpty(storagePools)) { + for (StoragePool storagePool : storagePools) { + String poolId = pool.getPoolId(); + String id = pool.getId(); + String storageId = pool.getStorageId(); + if (!StringUtils.isEmpty(poolId) && !StringUtils.isEmpty(id) && !StringUtils.isEmpty(storageId)) { + if (storagePool.getPoolId().equalsIgnoreCase(poolId) && + storagePool.getId().equals(id) && + storagePool.getStorageId().equalsIgnoreCase(storageId)) { + serverLevels.add(serviceLevel); + break; + } + } else { + log.error("query service Level error, storage pool is NULL!"); + throw new DmeException("query service Level error, storage pool list is NULL!"); + } + } + } + } + return serverLevels; + } + + private Volume findOrientedVolumeMapping(String volumeId) throws DmeException { + Volume volume = new Volume(); + String url = DmeConstants.DME_QUERY_ONE_VOLUME.replace("{volume_id}", volumeId); + ResponseEntity entity = dmeAccessService.access(url, HttpMethod.GET, null); + if (entity.getStatusCodeValue() == HttpStatus.OK.value()) { + String body = entity.getBody(); + + if (StringUtils.isEmpty(body)) { + throw new DmeException("query oriented volume is null!{}", volumeId); + } + JsonObject volumeObj = new JsonParser().parse(entity.getBody()).getAsJsonObject().get("volume").getAsJsonObject(); + log.info("query oriented volume ,{}", volumeObj); + boolean attached = ToolUtils.jsonToBoo(volumeObj.get("attached")); + if (!attached) { + throw new DmeException("query oriented volume attached status is unmapping!{}", volumeId); + } + volume.setStorageId(ToolUtils.jsonToStr(volumeObj.get("storage_id"))); + volume.setId(ToolUtils.jsonToStr(volumeObj.get("id"))); + volume.setServiceLevelName(ToolUtils.jsonToStr(volumeObj.get("service_level_name"))); + volume.setPoolRawId(ToolUtils.jsonToStr(volumeObj.get("pool_raw_id"))); + } + return volume; + } + @Override public void updateVmwarePolicy() throws DmeException { try { diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/services/TaskService.java b/dmestore-service/src/main/java/com/huawei/dmestore/services/TaskService.java index 9236e2934..7604e508c 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/services/TaskService.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/services/TaskService.java @@ -3,6 +3,8 @@ import com.huawei.dmestore.exception.DmeException; import com.huawei.dmestore.model.TaskDetailInfo; import com.google.gson.JsonObject; +import com.huawei.dmestore.model.TaskDetailInfoNew; +import com.huawei.dmestore.model.TasksResultObject; import java.util.List; import java.util.Map; @@ -69,4 +71,18 @@ public interface TaskService { * @throws DmeException DmeException **/ JsonObject queryTaskByIdUntilFinish(String taskId) throws DmeException; + /** + * checkTaskStatusNew + * + * @param taskId timeout + * @return TasksResultObject + **/ + TasksResultObject checkTaskStatusNew(String taskId, long timeout); + /** + * get task by id + * + * @param taskId taskId + * @return TaskDetailInfo TaskDetailInfo + **/ + TaskDetailInfoNew queryTaskByIdReturnMainTask(String taskId, long timeout); } diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/services/TaskServiceImpl.java b/dmestore-service/src/main/java/com/huawei/dmestore/services/TaskServiceImpl.java index 411fe73a5..83c23d329 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/services/TaskServiceImpl.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/services/TaskServiceImpl.java @@ -4,7 +4,9 @@ import com.huawei.dmestore.exception.DmeException; import com.huawei.dmestore.exception.DmeSqlException; import com.huawei.dmestore.model.TaskDetailInfo; +import com.huawei.dmestore.model.TaskDetailInfoNew; import com.huawei.dmestore.model.TaskDetailResource; +import com.huawei.dmestore.model.TasksResultObject; import com.huawei.dmestore.utils.ToolUtils; import com.google.gson.Gson; @@ -18,6 +20,7 @@ import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.util.ArrayList; @@ -28,6 +31,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; /** * TaskServiceImpl @@ -410,4 +414,211 @@ public void setDmeAccessService(DmeAccessService dmeAccessService) { public DmeAccessService getDmeAccessService() { return dmeAccessService; } + + + /** + * @Description: 新方法-检查任务状态 + * @Param taskId,timeout + * @return TasksResultObject + * @author yc + * @Date 2021/5/21 15:38 + */ + @Override + public TasksResultObject checkTaskStatusNew(String taskId, long timeout) { + //首先进行参数判断 + if(StringUtils.isEmpty(taskId)){ + return new TasksResultObject(true); + } + //设置方法的默认超时时间为3分钟 + long overTime = 3*60*1000; + if (0!= timeout){ + overTime = timeout; + } + long currentmilitions=System.currentTimeMillis(); + TasksResultObject result = new TasksResultObject(); + do{ + try { + //程序每次进入等待2秒 + TimeUnit.SECONDS.sleep(2); + } catch (InterruptedException e) { + LOG.info("===wait one secend error==={}", e.getMessage()); + } + //首先根据任务号查询任务状态 + result = queryTaskByIdNew(taskId); + if (StringUtils.isEmpty(result)){ + return null; + }else if (result.isStatus()){ + return result; + } + }while (System.currentTimeMillis()-overTime < currentmilitions); + return result; + } + + /** + * @Description: 根据任务号查询任务结果,并且分组统计 + * @Param @param null + * @return @return + * @throws + * @author yc + * @Date 2021/5/21 15:16 + */ + private TasksResultObject queryTaskByIdNew(String taskId) { + String url = DmeConstants.QUERY_TASK_URL.replace("{task_id}", taskId); + ResponseEntity responseEntity; + try { + //调用接口查询任务状态 + responseEntity = dmeAccessService.access(url, HttpMethod.GET, null); + if (responseEntity.getStatusCodeValue() != HttpStatus.OK.value() || StringUtils.isEmpty(responseEntity.getBody())) { + LOG.error("queryTaskById failed!taskId={},errorMsg:{}", taskId, responseEntity.getBody()); + return null; + } + // 解析返回结果,返回任务状态和成功或者失败的 + List taskInfos = analyzeTaskRequestResult(responseEntity.getBody()); + TasksResultObject resultMap = analyzeTaskDetailInfo(taskId,taskInfos); + if (StringUtils.isEmpty(resultMap)) { + return null; + } + return resultMap; + } catch (DmeException ex) { + LOG.error("queryTaskById error, errorMsg:{}", ex.getMessage()); + return null; + } + } + + + /** + * @Description: 获取任务对应的子任务集合 + * @Param body + * @return List + * @author yc + * @Date 2021/5/21 11:44 + */ + private List analyzeTaskRequestResult(String body) { + if (StringUtils.isEmpty(body)){ + return null; + } + JsonArray jsonArray; + if (body.contains("total") && body.contains("tasks")) { + JsonObject jsonObject = new JsonParser().parse(body).getAsJsonObject(); + jsonArray = jsonObject.get("tasks").getAsJsonArray(); + } else { + jsonArray = new JsonParser().parse(body).getAsJsonArray(); + } + List taskDetailInfoList = new ArrayList<>(); + if (CollectionUtils.isEmpty(Collections.singleton(jsonArray))){ + return null; + } + jsonArray.forEach(item -> { + TaskDetailInfoNew taskDetailInfo = new TaskDetailInfoNew(); + JsonObject jsonObject = item.getAsJsonObject(); + taskDetailInfo.setId(ToolUtils.jsonToStr(jsonObject.get("id"))); + taskDetailInfo.setNameCn(ToolUtils.jsonToStr(jsonObject.get("name_cn"))); + taskDetailInfo.setNameEn(ToolUtils.jsonToStr(jsonObject.get("name_en"))); + taskDetailInfo.setStatus(ToolUtils.jsonToInt(jsonObject.get("status"))); + taskDetailInfo.setProgress(ToolUtils.jsonToInt(jsonObject.get("progress"))); + taskDetailInfo.setOwnerName(ToolUtils.jsonToStr(jsonObject.get("owner_name"))); + taskDetailInfo.setOwnerId(ToolUtils.jsonToStr(jsonObject.get("owner_id"))); + taskDetailInfo.setStartTime(ToolUtils.getLong(jsonObject.get("create_time"))); + taskDetailInfo.setCreateTime(ToolUtils.getLong(jsonObject.get("create_time"))); + taskDetailInfo.setEndTime(ToolUtils.getLong(jsonObject.get("end_time"))); + taskDetailInfo.setDetailEn(ToolUtils.jsonToStr(jsonObject.get("detail_en"))); + taskDetailInfo.setDetailCn(ToolUtils.jsonToStr(jsonObject.get("detail_cn"))); + JsonArray resourcesArray = jsonObject.getAsJsonArray("resources"); + if (resourcesArray != null) { + List resourceList = getTaskDetailResources(resourcesArray); + taskDetailInfo.setResources(resourceList); + } + taskDetailInfoList.add(taskDetailInfo); + }); + return taskDetailInfoList; + } + /** + * @Description: 使用流的方式过滤子任务状态和进行统计 + * @Param @param null + * @return @return + * @throws + * @author yc + * @Date 2021/5/21 15:13 + */ + private TasksResultObject analyzeTaskDetailInfo(String taskId, List taskInfos) { + //首先判断任务集合是否为空 + if(CollectionUtils.isEmpty(taskInfos)){ + return null; + } + //根据taskid获取集合中对应的任务状态,如果为100,说明创建成功 + List taskDeatailInfos = + taskInfos.stream().filter(taskDetailInfoNew -> taskId.equalsIgnoreCase(taskDetailInfoNew.getId())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(taskDeatailInfos) || taskDeatailInfos.size()>1){ + return null; + } + String description = null; + if (100 == taskDeatailInfos.get(0).getProgress() || 3 < taskDeatailInfos.get(0).getStatus()){ + TasksResultObject tasksResultObject2 = new TasksResultObject(true); + description = taskDeatailInfos.get(0).getDetailEn(); + tasksResultObject2.setDescription(description); + return tasksResultObject2; + } + return new TasksResultObject(false); + } + + /** + * @return TaskDetailInfoNew + * @Description: 根据任务号查询任务状态,返回主任务状态 + * @Param taskId + * @author yc + * @Date 2021/5/31 14:57 + */ + @Override + public TaskDetailInfoNew queryTaskByIdReturnMainTask(String taskId,long overTime) { + String url = DmeConstants.QUERY_TASK_URL.replace("{task_id}", taskId); + ResponseEntity responseEntity; + long currentmilitions=System.currentTimeMillis(); + TaskDetailInfoNew taskDetailInfoNew = null; + try { + do{ + try { + //程序每次进入等待2秒 + TimeUnit.SECONDS.sleep(2); + } catch (InterruptedException e) { + LOG.info("===wait one secend error==={}", e.getMessage()); + } + //首先根据任务号查询任务状态 + responseEntity = dmeAccessService.access(url, HttpMethod.GET, null); + if (responseEntity.getStatusCodeValue() != HttpStatus.OK.value() || StringUtils.isEmpty(responseEntity.getBody())) { + LOG.error("queryTaskById failed!taskId={},errorMsg:{}", taskId, responseEntity.getBody()); + return null; + } + List taskInfos = analyzeTaskRequestResult(responseEntity.getBody()); + taskDetailInfoNew = getMainTaskInfo(taskId, taskInfos); + if (!StringUtils.isEmpty(taskDetailInfoNew) && (100 == taskDetailInfoNew.getProgress() || 3 < taskDetailInfoNew.getStatus())){ + return taskDetailInfoNew; + } + }while (System.currentTimeMillis()-overTime < currentmilitions); + } catch (DmeException ex) { + LOG.error("queryTaskById error, errorMsg:{}", ex.getMessage()); + } + return taskDetailInfoNew; + + } + + /** + * @return TaskDetailInfoNew + * @Description: 获取任务集合中的住任务状态 + * @Param taskId, taskInfos + * @author yc + * @Date 2021/5/31 15:02 + */ + private TaskDetailInfoNew getMainTaskInfo(String taskId, List taskInfos) { + //首先判断任务集合是否为空 + if (CollectionUtils.isEmpty(taskInfos)) { + return null; + } + //根据taskid获取集合中对应的任务状态 + List taskDeatailInfos = + taskInfos.stream().filter(taskDetailInfoNew -> taskId.equalsIgnoreCase(taskDetailInfoNew.getId())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(taskDeatailInfos) || taskDeatailInfos.size() > 1) { + return null; + } + return taskDeatailInfos.get(0); + } } diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/services/VmfsAccessService.java b/dmestore-service/src/main/java/com/huawei/dmestore/services/VmfsAccessService.java index b52499fc1..97b9466d4 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/services/VmfsAccessService.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/services/VmfsAccessService.java @@ -1,9 +1,7 @@ package com.huawei.dmestore.services; import com.huawei.dmestore.exception.DmeException; -import com.huawei.dmestore.model.ResponseBodyBean; -import com.huawei.dmestore.model.VmfsDataInfo; -import com.huawei.dmestore.model.VmfsDatastoreVolumeDetail; +import com.huawei.dmestore.model.*; import java.util.List; import java.util.Map; @@ -190,4 +188,49 @@ List> estimateConnectivityOfHostOrHostgroup(String storageId throws DmeException; Map>> getAllInitionator() throws DmeException ; + /** + * @Description: 创建Vmfs支持批量选择主机或者主机组 + * @Param @param null + * @return @return + * @throws + * @author yc + * @Date 2021/5/14 10:38 + */ + CreateVmfsResponse createVmfsNew(Map params) throws DmeException ; + /** + * @Description: vmfs挂载新方法,支持批量选择主机或者主机组 + * @Param @param null + * @return @return + * @throws + * @author yc + * @Date 2021/5/14 10:48 + */ + List> mountVmfsNew(Map params) throws DmeException; + /** + * @Description: 卸载页面,以树的形式返回可卸载的主机和集群(已过滤集群下未挂载的主机信息) + * @Param @param null + * @return @return + * @throws + * @author yc + * @Date 2021/5/14 16:17 + */ + List getMountedHostGroupsAndHostReturnTree(String dataStoreObjectId) throws Exception; + /** + * @Description: vfms卸载功能新接口 + * @Param @param null + * @return @return + * @throws + * @author yc + * @Date 2021/5/14 16:17 + */ + // void unmountVmfsNew(Map params) throws DmeException; + /** + * @Description: 查询存储设备的创建方式 + * @Param dataStoreObjectIds + * @return @return + * @throws String + * @author yc + * @Date 2021/6/2 15:29 + */ + String queryCreationMethodByDatastore(String dataStoreObjectId) throws DmeException; } diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/services/VmfsAccessServiceImpl.java b/dmestore-service/src/main/java/com/huawei/dmestore/services/VmfsAccessServiceImpl.java index 4f90f431c..a9ae795ee 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/services/VmfsAccessServiceImpl.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/services/VmfsAccessServiceImpl.java @@ -8,17 +8,8 @@ import com.huawei.dmestore.exception.DmeException; import com.huawei.dmestore.exception.DmeSqlException; import com.huawei.dmestore.exception.VcenterException; -import com.huawei.dmestore.model.SmartQos; -import com.huawei.dmestore.model.Storage; -import com.huawei.dmestore.model.StorageDetail; -import com.huawei.dmestore.model.StorageTypeShow; -import com.huawei.dmestore.model.TaskDetailInfo; -import com.huawei.dmestore.model.VmfsDataInfo; -import com.huawei.dmestore.model.VmfsDatastoreVolumeDetail; -import com.huawei.dmestore.utils.RestUtils; -import com.huawei.dmestore.utils.StringUtil; -import com.huawei.dmestore.utils.ToolUtils; -import com.huawei.dmestore.utils.VCSDKUtils; +import com.huawei.dmestore.model.*; +import com.huawei.dmestore.utils.*; import com.google.gson.Gson; import com.google.gson.JsonArray; @@ -27,19 +18,25 @@ import com.google.gson.JsonParser; import com.google.gson.reflect.TypeToken; +import org.apache.juli.logging.Log; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; +import javax.validation.constraints.NotNull; +import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; +import java.util.stream.Collectors; /** * VmfsAccessServiceImpl @@ -53,6 +50,8 @@ public class VmfsAccessServiceImpl implements VmfsAccessService { private static final String VOLUME_IDS = "volume_ids"; + private static final String VOLUME_ID = "volume_id"; + private static final String HOST_OBJ_IDS = "hostObjIds"; private static final String HOST_GROUP_ID = "hostGroupId"; @@ -93,10 +92,14 @@ public class VmfsAccessServiceImpl implements VmfsAccessService { private static final String HOSTID = "hostId"; + private static final String HOSTIDS = "hostIds"; + private static final String STORAGEID_VOLUMEIDS = "storageId_volumeIds"; private static final String HOST = "host"; + private static final String CLUSTER = "cluster"; + private static final String CLUSTER_ID = "clusterId"; private static final String TUNING = "tuning"; @@ -139,10 +142,19 @@ public class VmfsAccessServiceImpl implements VmfsAccessService { private static final String DATASTORE_OBJECT_IDS = "dataStoreObjectIds"; + private static final String CHOOSEDEVICE = "chooseDevice"; + + private static final String TYPE = "type"; + private static final String FIEL_SEPARATOR = "/"; + private static final String HOST_GROUP_VIEW_TYPE = "host_group"; + private static final int DEFAULT_LEN = 16; + private static final String CLUSTER_NAME = "clusterName"; + + private static final String IP_FIELD = "ip"; /** * 轮询任务状态的超值时间,这里设置超长,避免创建超多的lun超时 */ @@ -162,6 +174,9 @@ public class VmfsAccessServiceImpl implements VmfsAccessService { private DmeStorageService dmeStorageService; + @Autowired + private VmwareAccessServiceImpl vmwareAccessService; + private TaskService taskService; private VCSDKUtils vcsdkUtils; @@ -242,7 +257,7 @@ public List listVmfs() throws DmeException { int k = 0; Map tm = new HashMap<>(); long start1 = System.currentTimeMillis(); - getVmfsSync(volIds,relists,stoNameMap); + getVmfsSync(volIds, relists, stoNameMap); LOG.info("vmfs list response:{}ms", System.currentTimeMillis() - start1); } } else { @@ -257,12 +272,12 @@ public List listVmfs() throws DmeException { public synchronized void getVmfsSync(Map volIds, List vmfsDataInfos, Map stoNameMap) throws DmeException { Map requestbody = new HashMap<>(); - int total=0; - int pageno=1; - int allpageno=1; + int total = 0; + int pageno = 1; + int allpageno = 1; CountDownLatch countDownLatch = new CountDownLatch(volIds.size()); List volumeobjectlist = new ArrayList<>(); - while (pageno<=allpageno) { + while (pageno <= allpageno) { requestbody.put("page_no", pageno); requestbody.put("page_size", 1000); @@ -291,10 +306,9 @@ public synchronized void getVmfsSync(Map volIds, List entry: volIds.entrySet()){ - threadPoolExecutor.execute(()->{ - getVmfsDetailFromDme(vmfsDataInfos, stoNameMap, entry.getValue(),entry.getKey(), volumeobjectlist); + for (Map.Entry entry : volIds.entrySet()) { + threadPoolExecutor.execute(() -> { + getVmfsDetailFromDme(vmfsDataInfos, stoNameMap, entry.getValue(), entry.getKey(), volumeobjectlist); countDownLatch.countDown(); }); } @@ -306,13 +320,13 @@ public synchronized void getVmfsSync(Map volIds, List relists, Map stoNameMap, - VmfsDataInfo vmfsDataInfo, String volumeid,List volumeobjectlist) { - // String detailedVolumeUrl = DmeConstants.DME_VOLUME_BASE_URL + FIEL_SEPARATOR + volumeId; + VmfsDataInfo vmfsDataInfo, String volumeid, List volumeobjectlist) { + // String detailedVolumeUrl = DmeConstants.DME_VOLUME_BASE_URL + FIEL_SEPARATOR + volumeId; try { //ResponseEntity responseEntity = dmeAccessService.access(detailedVolumeUrl, HttpMethod.GET, null); - // if (responseEntity.getStatusCodeValue() == RestUtils.RES_STATE_I_200) { - // JsonObject voljson = new JsonParser().parse(responseEntity.getBody().toString()).getAsJsonObject(); - for (JsonObject jsonObject:volumeobjectlist){ + // if (responseEntity.getStatusCodeValue() == RestUtils.RES_STATE_I_200) { + // JsonObject voljson = new JsonParser().parse(responseEntity.getBody().toString()).getAsJsonObject(); + for (JsonObject jsonObject : volumeobjectlist) { //JsonObject vjson2 = new JsonObject();//voljson.getAsJsonObject(VOLUME_FIELD); if (volumeid.equalsIgnoreCase(ToolUtils.jsonToStr(jsonObject.get(ID_FIELD)))) { @@ -335,7 +349,7 @@ private void getVmfsDetailFromDme(List relists, Map listVmfsPerformance(List wwns) throws DmeExcep vmfsDataInfo.setVolumeId(wwn); vmfsDataInfo.setWwn(wwn); vmfsDataInfo.setIops(ToolUtils.jsonToFloat(ToolUtils.getStatistcValue(statisticObject, - DmeIndicatorConstants.COUNTER_ID_VOLUME_THROUGHPUT, MAX), null)); + DmeIndicatorConstants.COUNTER_ID_VOLUME_THROUGHPUT, MAX), null)); vmfsDataInfo.setBandwidth(ToolUtils.jsonToFloat(ToolUtils.getStatistcValue(statisticObject, - DmeIndicatorConstants.COUNTER_ID_VOLUME_BANDWIDTH, MAX), null)); + DmeIndicatorConstants.COUNTER_ID_VOLUME_BANDWIDTH, MAX), null)); vmfsDataInfo.setReadResponseTime(ToolUtils.jsonToFloat( - ToolUtils.getStatistcValue(statisticObject, - DmeIndicatorConstants.COUNTER_ID_VOLUME_READRESPONSETIME, MAX), null)); + ToolUtils.getStatistcValue(statisticObject, + DmeIndicatorConstants.COUNTER_ID_VOLUME_READRESPONSETIME, MAX), null)); vmfsDataInfo.setWriteResponseTime(ToolUtils.jsonToFloat( - ToolUtils.getStatistcValue(statisticObject, - DmeIndicatorConstants.COUNTER_ID_VOLUME_WRITERESPONSETIME, MAX), null)); + ToolUtils.getStatistcValue(statisticObject, + DmeIndicatorConstants.COUNTER_ID_VOLUME_WRITERESPONSETIME, MAX), null)); vmfsDataInfo.setLatency(ToolUtils.jsonToFloat(ToolUtils.getStatistcValue(statisticObject, - DmeIndicatorConstants.COUNTER_ID_VOLUME_RESPONSETIME, MAX), null)); + DmeIndicatorConstants.COUNTER_ID_VOLUME_RESPONSETIME, MAX), null)); relists.add(vmfsDataInfo); } } @@ -408,8 +422,8 @@ public List listVmfsPerformance(List wwns) throws DmeExcep return relists; } - public Map>> getAllInitionator() throws DmeException { - Map>> hostinitionators=new HashMap<>(); + public Map>> getAllInitionator() throws DmeException { + Map>> hostinitionators = new HashMap<>(); // 取出所有主机 LOG.info("get all getAllInitionator"); List> hostlist = dmeAccessService.getDmeHosts(null); @@ -423,13 +437,13 @@ public Map>> getAllInitionator() throws DmeExcep String demHostId = ToolUtils.getStr(hostmap.get(ID_FIELD)); // 得到主机的启动器 - List> initiators = dmeAccessService.getDmeHostInitiators(demHostId); + List> initiators = dmeAccessService.getDmeHostInitiators(demHostId); if (initiators != null && initiators.size() > 0) { hostinitionators.put(demHostId, initiators); } } } - LOG.info("get all getAllInitionator size="+hostinitionators.size()); + LOG.info("get all getAllInitionator size=" + hostinitionators.size()); return hostinitionators; } @@ -447,7 +461,7 @@ public List> createVmfs(Map params) throws D List volumeIds = new ArrayList<>(); boolean isCreated = false; boolean isMappling = false; - Map>> allinitionators=getAllInitionator(); + Map>> allinitionators = getAllInitionator(); try { // 根据服务等级ID获取对应的存储设备ID Object storageId = params.get(STORAGE_ID); @@ -459,7 +473,7 @@ public List> createVmfs(Map params) throws D LOG.info("create vms checkOrCreateToHostorHostGroup2"); - String objectid = checkOrCreateToHostorHostGroupnotest(params,allinitionators); + String objectid = checkOrCreateToHostorHostGroupnotest(params, allinitionators); List> hostIds = new ArrayList<>(); if (params != null && params.get(DmeConstants.HOST) != null) { // 根据获取到的dme主机,检查主机连通性 @@ -496,28 +510,28 @@ public List> createVmfs(Map params) throws D Set taskIds = new HashSet<>(); taskIds.add(taskId); isCreated = taskService.checkTaskStatusLarge(taskIds, longTaskTimeOut); - LOG.info("create vms isCreated"+isCreated); + LOG.info("create vms isCreated" + isCreated); // 查询看创建任务是否完成。 if (isCreated) { if (volumelist.size() == 0) { volumelist = getVolumeByName(ToolUtils.getStr(params.get(VOLUMENAME)), - null, null, ToolUtils.getStr(params.get(SERVICE_LEVEL_ID)), - ToolUtils.getStr(params.get(STORAGE_ID)), ToolUtils.getStr(params.get(POOL_RAW_ID))); + null, null, ToolUtils.getStr(params.get(SERVICE_LEVEL_ID)), + ToolUtils.getStr(params.get(STORAGE_ID)), ToolUtils.getStr(params.get(POOL_RAW_ID))); } - LOG.info("create vms volumelist size="+volumelist.size()); + LOG.info("create vms volumelist size=" + volumelist.size()); volumeIds = getVolumeId(volumelist); Set umaplist = new HashSet<>(); List lunids = new ArrayList<>(); for (String volumeId : volumeIds) { if (!StringUtils.isEmpty(volumeId)) { - params.put("volume_id", volumeId); + params.put(VOLUME_ID, volumeId); } // 映射主机或者主机组 LOG.info("create vms 映射主机或者主机组"); lunids.add(volumeId); - if (params.get(DmeConstants.HOST) != null && lunids.size()==volumeIds.size()) { + if (params.get(DmeConstants.HOST) != null && lunids.size() == volumeIds.size()) { dmeHostId = objHostId; taskId = lunMappingToHostOrHostgroup(lunids, dmeHostId, null); } else if (params.get(DmeConstants.CLUSTER) != null) { @@ -529,13 +543,13 @@ public List> createVmfs(Map params) throws D umaplist.add(taskId); } LOG.info("start mapping task checking"); - isMappling = taskService.checkTaskStatusLarge(umaplist,longTaskTimeOut); + isMappling = taskService.checkTaskStatusLarge(umaplist, longTaskTimeOut); if (isCreated && isMappling) { // 创建了几个卷,就创建几个VMFS,用卷的wwn去找到lun if (volumelist != null && volumelist.size() > 0) { createOnVmware(params, volumelist); } - }else { + } else { TaskDetailInfo taskinfo = taskService.queryTaskById(taskId); if (taskinfo != null) { throw new DmeException( @@ -546,20 +560,20 @@ public List> createVmfs(Map params) throws D throw new DmeException("DME create vmfs volume error(task status is failure)!"); } } - }else { + } else { throw new DmeException("DME create vmfs volume error(task status is failure)!"); } } } catch (DmeException e) { LOG.info("start rollback createvmfs"); rollBack(volumeIds, dmeHostId, demHostGroupId, isCreated, isMappling); - throw new DmeException("create vmfs failed!",e.getMessage()); + throw new DmeException("create vmfs failed!", e.getMessage()); } return new ArrayList<>(); } - private void rollBack(List volumeIds,String dmeHostId,String demHostGroupId,Boolean isCreated,Boolean isMapping) throws DmeException { + private void rollBack(List volumeIds, String dmeHostId, String demHostGroupId, Boolean isCreated, Boolean isMapping) throws DmeException { ResponseEntity responseEntity = null; String taskId = ""; if (volumeIds.size() != 0) { @@ -577,13 +591,13 @@ private void rollBack(List volumeIds,String dmeHostId,String demHostGrou } if (responseEntity.getStatusCodeValue() == HttpStatus.ACCEPTED.value()) { taskId = ToolUtils.jsonToStr( - new JsonParser().parse(ToolUtils.getStr(responseEntity.getBody())).getAsJsonObject() - .get("task_id")); + new JsonParser().parse(ToolUtils.getStr(responseEntity.getBody())).getAsJsonObject() + .get("task_id")); } } Set taskIds = new HashSet<>(); taskIds.add(taskId); - if (taskId.equals("") || taskService.checkTaskStatusLarge(taskIds,longTaskTimeOut)) { + if (taskId.equals("") || taskService.checkTaskStatusLarge(taskIds, longTaskTimeOut)) { volumeDelete(requestParam); if (!StringUtils.isEmpty(demHostGroupId)) { deleteHostgroup(demHostGroupId); @@ -597,8 +611,8 @@ private ResponseEntity deleteHostgroup(String hostgroupId) throws DmeException { return dmeAccessService.access(url, HttpMethod.DELETE, null); } - private String lunMappingToHostOrHostgroup(List volumeIds,String hostId,String clusterId) - throws DmeException { + private String lunMappingToHostOrHostgroup(List volumeIds, String hostId, String clusterId) + throws DmeException { String url = ""; Map params = new HashMap<>(); @@ -634,10 +648,10 @@ private String createLun(Map params) throws DmeException { } - private List getVolumeId(List> volumeByName){ + private List getVolumeId(List> volumeByName) { List volumeIds = new ArrayList<>(); for (Map map : volumeByName) { - String volumeId = ToolUtils.getStr(map.get("volume_id")); + String volumeId = ToolUtils.getStr(map.get(VOLUME_ID)); volumeIds.add(volumeId); } return volumeIds; @@ -660,7 +674,7 @@ private void createOnVmware(Map params, List if (!StringUtils.isEmpty(params.get(DmeConstants.SERVICELEVELID))) { vcenterinfo = vcenterinfoservice.getVcenterInfo(); } - final VCenterInfo vcentertemp=vcenterinfo; + final VCenterInfo vcentertemp = vcenterinfo; //创建前先扫描hba,避免每次循环扫描 String hostObjectId = ToolUtils.getStr(params.get(HOSTID)); @@ -673,36 +687,36 @@ private void createOnVmware(Map params, List CountDownLatch countDownLatch = new CountDownLatch(volumelist.size()); for (Map volumemap : volumelist) { - // threadPoolExecutor.submit(()->{ - Map paramstemp = new HashMap<>(params); - try { - // 创建vmware中的vmfs存储。 - paramstemp.put(VOLUME_WWN, volumemap.get(VOLUME_WWN)); - paramstemp.put(VOLUME_NAME, volumemap.get(VOLUME_NAME)); - String dataStoreStr = createVmfsOnVmware(paramstemp); - if (!StringUtils.isEmpty(dataStoreStr)) { - Map dataStoreMap = gson.fromJson(dataStoreStr, - new TypeToken>() { - }.getType()); - if (dataStoreMap != null) { - // 将DME卷与vmfs的关系保存数据库,因为可以同时创建几个卷,无法在此得到对应关系,所以此处不再保存关系信息 - saveDmeVmwareRalation(volumemap, dataStoreMap); - - // 关联服务等级 - if (!StringUtils.isEmpty(paramstemp.get(SERVICE_LEVEL_ID))) { - String serviceLevelName = ToolUtils.getStr(paramstemp.get(SERVICE_LEVEL_NAME)); - vcsdkUtils.attachTag(ToolUtils.getStr(dataStoreMap.get("type")), - ToolUtils.getStr(dataStoreMap.get(ID_FIELD)), serviceLevelName, vcentertemp); - } + // threadPoolExecutor.submit(()->{ + Map paramstemp = new HashMap<>(params); + try { + // 创建vmware中的vmfs存储。 + paramstemp.put(VOLUME_WWN, volumemap.get(VOLUME_WWN)); + paramstemp.put(VOLUME_NAME, volumemap.get(VOLUME_NAME)); + String dataStoreStr = createVmfsOnVmware(paramstemp); + if (!StringUtils.isEmpty(dataStoreStr)) { + Map dataStoreMap = gson.fromJson(dataStoreStr, + new TypeToken>() { + }.getType()); + if (dataStoreMap != null) { + // 将DME卷与vmfs的关系保存数据库,因为可以同时创建几个卷,无法在此得到对应关系,所以此处不再保存关系信息 + saveDmeVmwareRalation(volumemap, dataStoreMap); + + // 关联服务等级 + if (!StringUtils.isEmpty(paramstemp.get(SERVICE_LEVEL_ID))) { + String serviceLevelName = ToolUtils.getStr(paramstemp.get(SERVICE_LEVEL_NAME)); + vcsdkUtils.attachTag(ToolUtils.getStr(dataStoreMap.get(TYPE)), + ToolUtils.getStr(dataStoreMap.get(ID_FIELD)), serviceLevelName, vcentertemp); } - } else { - throw new DmeException("vmware create vmfs error:" + params.get(VOLUME_NAME)); } - }catch (Exception e){ - LOG.info("vmware create vmfs error:" + params.get(VOLUME_NAME)); + } else { + throw new DmeException("vmware create vmfs error:" + params.get(VOLUME_NAME)); } - // countDownLatch.countDown(); - // }); + } catch (Exception e) { + LOG.info("vmware create vmfs error:" + params.get(VOLUME_NAME)); + } + // countDownLatch.countDown(); + // }); } /*try { countDownLatch.await(); @@ -767,7 +781,7 @@ private String createVmfsOnVmware(Map params) throws DmeExceptio int blockSize = ToolUtils.getInt(params.get("blockSize")); String unmapPriority = ToolUtils.getStr(params.get("spaceReclamationPriority")); dataStoreStr = vcsdkUtils.createVmfsDataStore(hsdmap, capacity, datastoreName, vmfsMajorVersion, - blockSize, unmapGranularity, unmapPriority); + blockSize, unmapGranularity, unmapPriority); // 如果创建成功,在集群中的其他主机上扫描并挂载datastore if (!StringUtils.isEmpty(clusterObjectId)) { @@ -797,10 +811,10 @@ private String createVmfsByServiceLevel2(Map params) throws DmeE requestbody.put(SERVICE_LEVEL_ID, ToolUtils.getStr(params.get(SERVICE_LEVEL_ID))); ResponseEntity responseEntity = dmeAccessService.access(DmeConstants.DME_VOLUME_BASE_URL, - HttpMethod.POST, gson.toJson(requestbody)); + HttpMethod.POST, gson.toJson(requestbody)); if (responseEntity.getStatusCodeValue() == RestUtils.RES_STATE_I_202) { JsonObject jsonObject = new JsonParser().parse(responseEntity.getBody().toString()) - .getAsJsonObject(); + .getAsJsonObject(); if (jsonObject != null && !ToolUtils.jsonIsNull(jsonObject.get(DmeConstants.TASKID))) { taskId = ToolUtils.jsonToStr(jsonObject.get(TASK_ID)); } @@ -822,16 +836,16 @@ private String createVmfsByUnServiceLevelNew2(Map params) throws if (params != null && params.get(DmeConstants.STORAGEID) != null) { Map requestbody = initCreateBody2(params); ResponseEntity responseEntity = dmeAccessService.access(DmeConstants.DME_CREATE_VOLUME_UNLEVEL_URL, - HttpMethod.POST, gson.toJson(requestbody)); + HttpMethod.POST, gson.toJson(requestbody)); if (responseEntity.getStatusCodeValue() == RestUtils.RES_STATE_I_202) { JsonObject jsonObject = new JsonParser().parse(responseEntity.getBody().toString()) - .getAsJsonObject(); + .getAsJsonObject(); if (jsonObject != null && !ToolUtils.jsonIsNull(jsonObject.get(DmeConstants.TASKID))) { taskId = ToolUtils.jsonToStr(jsonObject.get(TASK_ID)); } } else { throw new DmeException( - "create UNService Level volume error:" + responseEntity.getBody().toString()); + "create UNService Level volume error:" + responseEntity.getBody().toString()); } } else { throw new DmeException("create UNService Level volume parameters error."); @@ -871,7 +885,7 @@ private Map initCreateBody(Map params, String ob tuning.put("smart_qos", smartqos); } if (!StringUtils.isEmpty(params.get(DmeConstants.ALLOCTYPE)) || !StringUtils.isEmpty( - params.get(WORKLOAD_TYPE_ID)) || !StringUtils.isEmpty(params.get(CONTROL_POLICY))) { + params.get(WORKLOAD_TYPE_ID)) || !StringUtils.isEmpty(params.get(CONTROL_POLICY))) { requestbody.put(TUNING, tuning); } @@ -921,7 +935,7 @@ private Map initCreateBody2(Map params) { tuning.put("smart_qos", smartqos); } if (!StringUtils.isEmpty(params.get(DmeConstants.ALLOCTYPE)) || !StringUtils.isEmpty( - params.get(WORKLOAD_TYPE_ID)) || !StringUtils.isEmpty(params.get(CONTROL_POLICY))) { + params.get(WORKLOAD_TYPE_ID)) || !StringUtils.isEmpty(params.get(CONTROL_POLICY))) { requestbody.put(TUNING, tuning); } @@ -936,7 +950,7 @@ private Map initCreateBody2(Map params) { return requestbody; } - private String checkToHostAllInitiators(String vmwareHostObjId,Map>> allinitionators) throws DmeException { + private String checkToHostAllInitiators(String vmwareHostObjId, Map>> allinitionators) throws DmeException { if (StringUtils.isEmpty(vmwareHostObjId)) { return ""; } @@ -991,6 +1005,52 @@ private String checkToHostAllInitiators(String vmwareHostObjId,Map>> allinitionators, + List hostIds) throws DmeException { + if (StringUtils.isEmpty(vmwareHostObjId)) { + return ""; + } + + // 判断vcenter主机在DME中是否存在 + String objId = ""; + try { + // 通过主机的objectid查到主机上所有的hba的wwn或者iqn + List> hbas = vcsdkUtils.getHbasByHostObjectId(vmwareHostObjId); + LOG.info("==hbas 0f host on vcenter==", gson.toJson(hbas)); + if (hbas == null || hbas.size() == 0) { + throw new DmeException(vmwareHostObjId + " The host did not find a valid Hba"); + } + List wwniqns = new ArrayList<>(); + for (Map hba : hbas) { + wwniqns.add(ToolUtils.getStr(hba.get(NAME_FIELD))); + } + LOG.info("==hostlist on vcenter==", gson.toJson(wwniqns)); + // 取出DME所有主机 + //List> dmeHostlist = dmeAccessService.getDmeHosts(null); + if (CollectionUtils.isEmpty(hostIds)) { + LOG.error("volume mapped hosts params error!dme hosts is null"); + return ""; + } + for (String demHostId : hostIds) { + List> initiators = allinitionators.get(demHostId); + LOG.info("==initiators 0f host on vcenter==", gson.toJson(initiators)); + if (initiators != null && initiators.size() > 0) { + for (Map inimap : initiators) { + String portName = ToolUtils.getStr(inimap.get(PORT_NAME)); + if (wwniqns.contains(portName)) { + objId = demHostId; + break; + } + } + } + } + } catch (DmeException ex) { + LOG.error("checkToHost error:", ex); + throw new DmeException(ex.getMessage()); + } + return objId; + } + private String checkToHost(String vmwareHostObjId) throws DmeException { if (StringUtils.isEmpty(vmwareHostObjId)) { return ""; @@ -1047,7 +1107,7 @@ private String checkToHost(String vmwareHostObjId) throws DmeException { } @Override - public String checkOrCreateToHost(String hostIp, String hostId,Map>> allinitionators) throws DmeException { + public String checkOrCreateToHost(String hostIp, String hostId, Map>> allinitionators) throws DmeException { // 判断主机在DME中是否存在 如果主机不存在就创建并得到主机ID String objId = ""; try { @@ -1096,7 +1156,7 @@ public String checkOrCreateToHost(String hostIp, String hostId,Map> hostinitionators=allinitionators.get(dmehostid); + List> hostinitionators = allinitionators.get(dmehostid); if (hostinitionators != null && hostinitionators.size() > 0) { for (Map inimap : hostinitionators) { String portName = ToolUtils.getStr(inimap.get(PORT_NAME)); @@ -1110,11 +1170,13 @@ public String checkOrCreateToHost(String hostIp, String hostId,Map> estimateConnectivityOfHostOrHostgroup(String storageId, String hostId, - String hostgroupId) throws DmeException { + String hostgroupId) throws DmeException { Map requestBody = new HashMap<>(); if (StringUtils.isEmpty(storageId)) { @@ -1161,7 +1223,7 @@ public List> estimateConnectivityOfHostOrHostgroup(String st // 连通性异常主机结果统计 Map result = new HashMap<>(); if (status.equalsIgnoreCase("NOT_CONNECT")) { - //if (status.equalsIgnoreCase("FAILED")) { + //if (status.equalsIgnoreCase("FAILED")) { String hostName = getDmeHostNameById(id); //result.put(hostName, resultMessage); result.put(hostName, "启动器处于离线状态!"); @@ -1271,14 +1333,15 @@ private String getOrCreateHostGroupId(String clusterObjectId) throws DmeExceptio String vmwarehosts = vcsdkUtils.getHostsOnCluster(clusterObjectId); if (!StringUtils.isEmpty(vmwarehosts)) { List> vmwarehostlists = gson.fromJson(vmwarehosts, - new TypeToken>>() { }.getType()); + new TypeToken>>() { + }.getType()); if (vmwarehostlists != null && vmwarehostlists.size() > 0) { // 分别检查每一个主机是否存在,如果不存在就创建 - Map>> allinitionators=getAllInitionator(); + Map>> allinitionators = getAllInitionator(); List hostlists = new ArrayList<>(); for (Map hostmap : vmwarehostlists) { String tmpHostId = checkOrCreateToHost(ToolUtils.getStr(hostmap.get(HOST_NAME)), - ToolUtils.getStr(hostmap.get(HOSTID)),allinitionators); + ToolUtils.getStr(hostmap.get(HOSTID)), allinitionators); if (!StringUtils.isEmpty(tmpHostId)) { hostlists.add(tmpHostId); } @@ -1303,7 +1366,7 @@ private String getOrCreateHostGroupId(String clusterObjectId) throws DmeExceptio } private String getOrCreateHostGroupId2(String clusterObjectId, String volumeId) - throws DmeException { + throws DmeException { String objId = ""; @@ -1313,15 +1376,15 @@ private String getOrCreateHostGroupId2(String clusterObjectId, String volumeId) String vmwarehosts = vcsdkUtils.getHostsOnCluster(clusterObjectId); if (!StringUtils.isEmpty(vmwarehosts)) { List> vmwarehostlists = gson.fromJson(vmwarehosts, - new TypeToken>>() { - }.getType()); + new TypeToken>>() { + }.getType()); if (vmwarehostlists != null && vmwarehostlists.size() > 0) { // 分别检查每一个主机是否存在,如果不存在就创建 List hostlists = new ArrayList<>(); - Map>> allinitionators=getAllInitionator(); + Map>> allinitionators = getAllInitionator(); for (Map hostmap : vmwarehostlists) { String tmpHostId = checkOrCreateToHost(ToolUtils.getStr(hostmap.get(HOST_NAME)), - ToolUtils.getStr(hostmap.get(HOSTID)),allinitionators); + ToolUtils.getStr(hostmap.get(HOSTID)), allinitionators); if (!StringUtils.isEmpty(tmpHostId)) { hostlists.add(tmpHostId); } @@ -1333,7 +1396,7 @@ private String getOrCreateHostGroupId2(String clusterObjectId, String volumeId) } Map params = new HashMap<>(); params.put("cluster", - vcsdkUtils.getVcConnectionHelper().objectId2Mor(clusterObjectId).getValue() + "-" + subVolumeId); + vcsdkUtils.getVcConnectionHelper().objectId2Mor(clusterObjectId).getValue() + "-" + subVolumeId); params.put("hostids", hostlists); Map hostmap = dmeAccessService.createHostGroup(params); if (hostmap != null && hostmap.get(DmeConstants.ID) != null) { @@ -1387,7 +1450,8 @@ private String checkToHostGroup(String clusterObjectId) throws DmeException { String vmwarehosts = vcsdkUtils.getHostsOnCluster(clusterObjectId); if (!StringUtils.isEmpty(vmwarehosts)) { List> vmwarehostlists = gson.fromJson(vmwarehosts, - new TypeToken>>() { }.getType()); + new TypeToken>>() { + }.getType()); // 分别检查每一个主机是否存在,如果不存在就创建 List hostlists = new ArrayList<>(); @@ -1406,7 +1470,7 @@ private String checkToHostGroup(String clusterObjectId) throws DmeException { return objId; } - private Map getHostGroupMappingOrientedVolume(String clusterObjectId,List volumeIds) throws DmeException { + private Map getHostGroupMappingOrientedVolume(String clusterObjectId, List volumeIds) throws DmeException { Map hostgroupIDAndVolemeID = new HashMap<>(); try { // 获取到主机组列表 @@ -1470,7 +1534,7 @@ private String checkHostInHostGroup(String vmwareClusterObjectId, String dmeHost String demHostId = ToolUtils.getStr(dmehost.get(ID_FIELD)); List> subinitiators = dmeAccessService.getDmeHostInitiators(demHostId); LOG.info("initiators of host on dme!", - gson.toJson(initiators) + "host size:" + initiators.size()); + gson.toJson(initiators) + "host size:" + initiators.size()); if (subinitiators != null && subinitiators.size() > 0) { initiators.addAll(subinitiators); } @@ -1498,18 +1562,18 @@ private String checkHostInHostGroup(String vmwareClusterObjectId, String dmeHost return objId; } - private List> checkOrCreateToHostorHostGroup2(Map params,Map>> allinitionators) throws DmeException { + private List> checkOrCreateToHostorHostGroup2(Map params, Map>> allinitionators) throws DmeException { // 根据参数选择检查主机或主机组的方法 String objId = ""; List> hostIds = new ArrayList<>(); try { // param str host: 主机 param str cluster: 集群 if (params != null && params.get(DmeConstants.HOST) != null) { - objId = checkOrCreateToHost(ToolUtils.getStr(params.get(HOST)), ToolUtils.getStr(params.get(HOSTID)),allinitionators); + objId = checkOrCreateToHost(ToolUtils.getStr(params.get(HOST)), ToolUtils.getStr(params.get(HOSTID)), allinitionators); // 根据获取到的dme主机,检查主机连通性 hostIds = estimateConnectivityOfHostOrHostgroup(ToolUtils.getStr(params.get(STORAGE_ID)), objId, null); } else if (params != null && params.get(DmeConstants.CLUSTER) != null) { - objId = getOrCreateHostGroupId2(ToolUtils.getStr(params.get(CLUSTER_ID)),ToolUtils.getStr(params.get("volume_id"))); + objId = getOrCreateHostGroupId2(ToolUtils.getStr(params.get(CLUSTER_ID)), ToolUtils.getStr(params.get(VOLUME_ID))); // 检查主机组连通性 hostIds = estimateConnectivityOfHostOrHostgroup(ToolUtils.getStr(params.get(STORAGE_ID)), null, objId); } @@ -1527,18 +1591,18 @@ private List> checkOrCreateToHostorHostGroup2(Map params,Map>> allinitionators) throws DmeException { + private String checkOrCreateToHostorHostGroupnotest(Map params, Map>> allinitionators) throws DmeException { // 根据参数选择检查主机或主机组的方法 String objId = ""; List> hostIds = new ArrayList<>(); try { // param str host: 主机 param str cluster: 集群 if (params != null && params.get(DmeConstants.HOST) != null) { - objId = checkOrCreateToHost(ToolUtils.getStr(params.get(HOST)), ToolUtils.getStr(params.get(HOSTID)),allinitionators); + objId = checkOrCreateToHost(ToolUtils.getStr(params.get(HOST)), ToolUtils.getStr(params.get(HOSTID)), allinitionators); // 根据获取到的dme主机,检查主机连通性 //hostIds = estimateConnectivityOfHostOrHostgroup(ToolUtils.getStr(params.get(STORAGE_ID)), objId, null); } else if (params != null && params.get(DmeConstants.CLUSTER) != null) { - objId = getOrCreateHostGroupId2(ToolUtils.getStr(params.get(CLUSTER_ID)),ToolUtils.getStr(params.get("volume_id"))); + objId = getOrCreateHostGroupId2(ToolUtils.getStr(params.get(CLUSTER_ID)), ToolUtils.getStr(params.get(VOLUME_ID))); // 检查主机组连通性 //hostIds = estimateConnectivityOfHostOrHostgroup(ToolUtils.getStr(params.get(STORAGE_ID)), null, objId); } @@ -1556,7 +1620,7 @@ private String checkOrCreateToHostorHostGroupnotest(Map params,M return objId; } - private String getVolumeIdByStoreId (String storeId) throws DmeSqlException { + private String getVolumeIdByStoreId(String storeId) throws DmeSqlException { String volumeId = ""; try { if (!StringUtils.isEmpty(storeId)) { @@ -1583,7 +1647,7 @@ private String getStorageIdByVolumeId(String volumeId) throws DmeException { } private List> getVolumeByName(String volumeName, String hostId, String hostGroupId, - String serviceLevelId, String storageId, String poolRawId) { + String serviceLevelId, String storageId, String poolRawId) { // 根据卷名称,主机id,主机组id,服务等级id,存储设备ID,存储池ID 查询DME卷的信息 List> volumelist = null; String listVolumeUrl = DmeConstants.DME_VOLUME_BASE_URL + "?name=" + volumeName; @@ -1604,7 +1668,7 @@ private List> getVolumeByName(String volumeName, String host listVolumeUrl = listVolumeUrl + "&id=" + poolRawId; } try { - LOG.info("getallvolume url="+listVolumeUrl); + LOG.info("getallvolume url=" + listVolumeUrl); ResponseEntity responseEntity = dmeAccessService.access(listVolumeUrl, HttpMethod.GET, null); if (responseEntity.getStatusCodeValue() == RestUtils.RES_STATE_I_200) { JsonObject jsonObject = new JsonParser().parse(responseEntity.getBody().toString()).getAsJsonObject(); @@ -1615,7 +1679,7 @@ private List> getVolumeByName(String volumeName, String host if (vjson != null) { Map remap = new HashMap<>(); remap.put("storage_id", storageId); - remap.put("volume_id", ToolUtils.jsonToStr(vjson.get(ID_FIELD))); + remap.put(VOLUME_ID, ToolUtils.jsonToStr(vjson.get(ID_FIELD))); remap.put(VOLUME_NAME, ToolUtils.jsonToStr(vjson.get(NAME_FIELD))); remap.put(VOLUME_WWN, ToolUtils.jsonToStr(vjson.get(VOLUME_WWN))); volumelist.add(remap); @@ -1629,7 +1693,7 @@ private List> getVolumeByName(String volumeName, String host } private void saveDmeVmwareRalation(Map volumeMap, Map dataStoreMap) - throws DmeException { + throws DmeException { // 保存卷与vmfs的关联关系 if (volumeMap == null || volumeMap.get(DmeConstants.VOLUMEID) == null) { LOG.error("save Dme and Vmware's vmfs Ralation error: volume data is null"); @@ -1642,7 +1706,7 @@ private void saveDmeVmwareRalation(Map volumeMap, Map> mountVmfs(Map params) throws Dm // param str host: 主机 param str cluster: 集群 dataStoreObjectIds // 判断主机或主机组在DME中是否存在, 如果主机或主机不存在就创建并得到主机或主机组ID // 接入主机连通性检查 - Map> storageIdMaps = (Map>)params.get(STORAGEID_VOLUMEIDS); - Map>> allinitionators=getAllInitionator(); + Map> storageIdMaps = (Map>) params.get(STORAGEID_VOLUMEIDS); + Map>> allinitionators = getAllInitionator(); if (storageIdMaps != null && storageIdMaps.size() != 0) { for (Map.Entry> entry : storageIdMaps.entrySet()) { params.put(STORAGE_ID, entry.getKey()); for (String volumeId : entry.getValue()) { - params.put("volume_id", volumeId); - maps = checkOrCreateToHostorHostGroup2(params,allinitionators); + params.put(VOLUME_ID, volumeId); + maps = checkOrCreateToHostorHostGroup2(params, allinitionators); if (maps.size() != 0) { for (Map map : maps) { objhostid = map.get(CONNECTIVITY_NORMAL); @@ -1753,7 +1817,7 @@ public List> mountVmfs(Map params) throws Dm } private void getVolumIdFromLocal2(Map params, List dataStoreObjectIds) - throws DmeSqlException { + throws DmeSqlException { List volumeIds = new ArrayList<>(); List dataStoreNames = new ArrayList<>(); Map> storageIds = new HashMap<>(); @@ -1764,7 +1828,7 @@ private void getVolumIdFromLocal2(Map params, List dataS String storageDeviceId = dvr.getStorageDeviceId(); if (storageIds.get(storageDeviceId) != null) { storageIds.get(storageDeviceId).add(dvr.getVolumeId()); - }else { + } else { List volumeIdList = new ArrayList<>(); volumeIdList.add(dvr.getVolumeId()); storageIds.put(storageDeviceId, volumeIdList); @@ -1793,7 +1857,7 @@ private void mountVmfsOnVmware(Map params) throws VcenterExcepti dsmap.put(NAME_FIELD, dataStoreName); vcsdkUtils.mountVmfsOnCluster(gson.toJson(dsmap), ToolUtils.getStr(params.get(CLUSTER_ID)), - ToolUtils.getStr(params.get(HOSTID))); + ToolUtils.getStr(params.get(HOSTID))); } } } @@ -1810,10 +1874,10 @@ private String mountVmfsToHost(Map params, String objhostid) { requestbody.put(VOLUME_IDS, volumeIds); requestbody.put(HOST_ID, objhostid); ResponseEntity responseEntity = dmeAccessService.access(DmeConstants.DME_HOST_MAPPING_URL, - HttpMethod.POST, gson.toJson(requestbody)); + HttpMethod.POST, gson.toJson(requestbody)); if (responseEntity.getStatusCodeValue() == RestUtils.RES_STATE_I_202) { JsonObject jsonObject = new JsonParser().parse(responseEntity.getBody().toString()) - .getAsJsonObject(); + .getAsJsonObject(); if (jsonObject != null && jsonObject.get(DmeConstants.TASKID) != null) { taskId = ToolUtils.jsonToStr(jsonObject.get(TASK_ID)); } @@ -1839,10 +1903,10 @@ private String mountVmfsToHostGroup(Map params, String objhostid requestbody.put(HOST_GROUP_ID1, objhostid); ResponseEntity responseEntity = dmeAccessService.access(DmeConstants.MOUNT_VOLUME_TO_HOSTGROUP_URL, - HttpMethod.POST, gson.toJson(requestbody)); + HttpMethod.POST, gson.toJson(requestbody)); if (responseEntity.getStatusCodeValue() == RestUtils.RES_STATE_I_202) { JsonObject jsonObject = new JsonParser().parse(responseEntity.getBody().toString()) - .getAsJsonObject(); + .getAsJsonObject(); if (jsonObject != null && jsonObject.get(DmeConstants.TASKID) != null) { taskId = ToolUtils.jsonToStr(jsonObject.get(TASK_ID)); LOG.info("mountVmfsToHostGroup task_id===={}", taskId); @@ -1883,7 +1947,7 @@ public List volumeDetail(String storageObjectId) thro volumeDetail.setName(volume.get(NAME_FIELD).getAsString()); volumeDetail.setServiceLevel(ToolUtils.jsonToStr(volume.get(SERVICE_LEVEL_NAME), null)); if (!volume.get(STORAGE_ID).isJsonNull()) { - storageId = volume.get(STORAGE_ID).getAsString(); + storageId = volume.get(STORAGE_ID).getAsString(); // 根据存储ID查询存储信息 url = DmeConstants.DME_STORAGE_DETAIL_URL.replace("{storage_id}", storageId); @@ -1895,7 +1959,7 @@ public List volumeDetail(String storageObjectId) thro } if (!volume.get(POOL_RAW_ID).isJsonNull()) { - parseStoragePool(volume.get(POOL_RAW_ID).getAsString(), volumeDetail,storageId); + parseStoragePool(volume.get(POOL_RAW_ID).getAsString(), volumeDetail, storageId); } JsonObject tuning = volume.getAsJsonObject(TUNING); @@ -1911,33 +1975,34 @@ public List volumeDetail(String storageObjectId) thro replaceSpecChar(list); return list; } + /** - * @Description: 替换卷页面展示的&问题 - * @Param @param null - * @return @return - * @throws - * @author yc - * @Date 2021/4/20 18:29 + * @return @return + * @throws + * @Description: 替换卷页面展示的&问题 + * @Param @param null + * @author yc + * @Date 2021/4/20 18:29 */ private void replaceSpecChar(List list) { - for (VmfsDatastoreVolumeDetail volumeDetail:list) { - if(null != volumeDetail){ - if(!StringUtils.isEmpty(volumeDetail.getApplicationType())){ - volumeDetail.setApplicationType(volumeDetail.getApplicationType().replace("&","&")); + for (VmfsDatastoreVolumeDetail volumeDetail : list) { + if (null != volumeDetail) { + if (!StringUtils.isEmpty(volumeDetail.getApplicationType())) { + volumeDetail.setApplicationType(volumeDetail.getApplicationType().replace("&", "&")); } } } } - private String getWorkLoadNameById(String storageId,String workLoadType) throws DmeException { + private String getWorkLoadNameById(String storageId, String workLoadType) throws DmeException { String name = ""; if (!StringUtils.isEmpty(storageId) && !StringUtils.isEmpty(workLoadType)) { String workloadsUrl = DmeConstants.GET_WORKLOADS_URL.replace("{storage_id}", storageId); ResponseEntity responseEntity = dmeAccessService.access(workloadsUrl, HttpMethod.GET, null); if (responseEntity.getStatusCodeValue() == RestUtils.RES_STATE_I_200) { JsonObject jsonObject = new JsonParser().parse(responseEntity.getBody().toString()) - .getAsJsonObject(); + .getAsJsonObject(); if (jsonObject != null && jsonObject.get(DmeConstants.DATAS) != null) { JsonArray jsonArray = jsonObject.getAsJsonArray(DmeConstants.DATAS); for (int index = 0; index < jsonArray.size(); index++) { @@ -1956,10 +2021,10 @@ private String getWorkLoadNameById(String storageId,String workLoadType) throws } - private void parseStoragePool(String poolId, VmfsDatastoreVolumeDetail volumeDetail,String storageDeviceId) throws DmeException { + private void parseStoragePool(String poolId, VmfsDatastoreVolumeDetail volumeDetail, String storageDeviceId) throws DmeException { String poolName = ""; try { - poolName = dmeStorageService.getStorageByPoolRawId(poolId,storageDeviceId); + poolName = dmeStorageService.getStorageByPoolRawId(poolId, storageDeviceId); } catch (DmeException ex) { LOG.info("query datastore pool failed!{}", ex.getMessage()); } @@ -2050,20 +2115,20 @@ public boolean scanVmfs() throws DmeException { } - private List splitOb(List obs){ + private List splitOb(List obs) { List r = new CopyOnWriteArrayList<>(); - for (Ob ob : obs){ - if (ob.wwns.size() > SIZE){ + for (Ob ob : obs) { + if (ob.wwns.size() > SIZE) { List wns = new ArrayList<>(); - for (int i=1; i <= ob.wwns.size(); i++){ - wns.add(ob.wwns.get(i-1)); - if (i % SIZE == 0){ + for (int i = 1; i <= ob.wwns.size(); i++) { + wns.add(ob.wwns.get(i - 1)); + if (i % SIZE == 0) { Ob o = new Ob(wns, ob.vmfsDatastoreId, ob.vmfsDatastoreName); r.add(o); wns = new ArrayList<>(); } } - if (wns.size() > 0){ + if (wns.size() > 0) { Ob o = new Ob(wns, ob.vmfsDatastoreId, ob.vmfsDatastoreName); r.add(o); } @@ -2075,13 +2140,13 @@ private List splitOb(List obs){ return r; } - static class Ob{ + static class Ob { List wwns; String storeType = DmeConstants.STORE_TYPE_VMFS; String vmfsDatastoreId; String vmfsDatastoreName; - private Ob(List wwns, String vmfsDatastoreId, String vmfsDatastoreName){ + private Ob(List wwns, String vmfsDatastoreId, String vmfsDatastoreName) { this.wwns = wwns; this.vmfsDatastoreId = vmfsDatastoreId; this.vmfsDatastoreName = vmfsDatastoreName; @@ -2092,7 +2157,7 @@ private Ob(List wwns, String vmfsDatastoreId, String vmfsDatastoreName){ public synchronized void getRelationSync(List obs, int size, Map storageIds, List relationList) throws DmeException { JsonArray volumeList = new JsonArray(); int offset = 0; - getVolumesRecursion(offset,volumeList); + getVolumesRecursion(offset, volumeList); if (null != volumeList && volumeList.size() > 0) { for (JsonElement volumeObjectelement : volumeList) { JsonObject volumeObject = volumeObjectelement.getAsJsonObject(); @@ -2118,35 +2183,36 @@ public synchronized void getRelationSync(List obs, int size, Mapoffset){ - getVolumesRecursion(offset,volumeList); - } + + private JsonArray getVolumesRecursion(int offset, JsonArray volumeList) throws DmeException { + int limit = 1000; + String volumeUrlByName = DmeConstants.DME_VOLUME_BASE_URL + "?offset=" + offset; + try { + ResponseEntity responseEntity = dmeAccessService.access(volumeUrlByName, HttpMethod.GET, null); + if (responseEntity.getStatusCodeValue() / DIVISOR_100 != HTTP_SUCCESS) { + LOG.info(" Query DME volume failed! errorMsg:{}", responseEntity.toString()); + } else { + JsonObject jsonObject = gson.fromJson(responseEntity.getBody(), JsonObject.class); + JsonElement volumesElement = jsonObject.get("volumes"); + int count = jsonObject.get("count").getAsInt(); + offset += limit; + if (!ToolUtils.jsonIsNull(volumesElement)) { + JsonArray volumeArray = volumesElement.getAsJsonArray(); + volumeList.addAll(volumeArray); + } + if (count > offset) { + getVolumesRecursion(offset, volumeList); } - } catch (DmeException e) { - LOG.warn("List volumes error", e); - throw new DmeException("List volumes error", e.getMessage()); } - return volumeList; + } catch (DmeException e) { + LOG.warn("List volumes error", e); + throw new DmeException("List volumes error", e.getMessage()); } + return volumeList; + } private DmeVmwareRelation getDmeVmwareRelation(String storeType, String vmfsDatastoreId, String vmfsDatastoreName, - JsonObject volumeObject, String storageModel,String deviceId) { + JsonObject volumeObject, String storageModel, String deviceId) { String volumeId = ToolUtils.jsonToOriginalStr(volumeObject.get(ID_FIELD)); String volumeName = ToolUtils.jsonToOriginalStr(volumeObject.get(NAME_FIELD)); String volumeWwn = ToolUtils.jsonToOriginalStr(volumeObject.get(VOLUME_WWN)); @@ -2165,7 +2231,7 @@ private DmeVmwareRelation getDmeVmwareRelation(String storeType, String vmfsData } private boolean dmeVmwareRelationDbProcess(List relationList, String storeType) - throws DmeSqlException { + throws DmeSqlException { // 本地全量查询 List localWwns = dmeVmwareRalationDao.getAllWwnByType(storeType); List storeIds = dmeVmwareRalationDao.getAllStorageIdByType(storeType); @@ -2204,24 +2270,29 @@ private boolean dmeVmwareRelationDbProcess(List relationList, public void unmountVmfs(Map params) throws DmeException { List taskIds = new ArrayList<>(); List dataStoreObjectIds = null; - String hostObjId = ""; + List hostObjIds = new ArrayList<>(); String clusterObjId = ""; List volumeIds = new ArrayList<>(); + Map volumeIdToStoreName = new HashMap<>(); + // 获取存储对应的卷Id并过滤绑掉虚拟机的存储 if (null != params && null != params.get(DATASTORE_OBJECT_IDS)) { dataStoreObjectIds = (List) params.get(DATASTORE_OBJECT_IDS); if (dataStoreObjectIds.size() > 0) { List dataStoreNames = new ArrayList<>(); + //Map storeToHost = new HashMap<>(); + List bounds = new ArrayList<>(); for (String dsObjectId : dataStoreObjectIds) { - boolean isFoundVm = vcsdkUtils.hasVmOnDatastore(dsObjectId); - if (isFoundVm) { - LOG.info("vmfs unmount,the vmfs:{} contain vm,can not unmount!!!", dsObjectId); - continue; - } DmeVmwareRelation dvr = dmeVmwareRalationDao.getDmeVmwareRelationByDsId(dsObjectId); if (dvr == null) { scanVmfs(); + dvr = dmeVmwareRalationDao.getDmeVmwareRelationByDsId(dsObjectId); + } + boolean isFoundVm = vcsdkUtils.hasVmOnDatastore(dsObjectId); + if (isFoundVm) { + bounds.add(dvr.getStoreName()); + LOG.error("vmfs unmount,the vmfs:{} contain vm,can not unmount!!!", dsObjectId); + continue; } - dvr = dmeVmwareRalationDao.getDmeVmwareRelationByDsId(dsObjectId); if (dvr != null) { volumeIds.add(dvr.getVolumeId()); dataStoreNames.add(dvr.getStoreName()); @@ -2230,112 +2301,158 @@ public void unmountVmfs(Map params) throws DmeException { if (volumeIds.size() > 0) { params.put(VOLUMEIDS, volumeIds); params.put(DATASTORE_NAMES, dataStoreNames); + } else { + throw new DmeException("the vmfs:"+bounds+" contain virtual machine,can not unmount!"); } } else { - throw new DmeException("unmount volume params dataStoreObjectIds is null!"); + throw new DmeException("unmount volume params datastore ids is null!"); } } - boolean isUnmounted = false; + List dmeHostIds = new ArrayList<>(); + List>> needUnmapped = new ArrayList<>(); if (params != null && volumeIds.size() != 0) { - - if (params.get(HOSTID) != null) { - hostObjId = ToolUtils.getStr(params.get(HOSTID)); - Map hostMap = getDmeHostByHostObjeId2(hostObjId); - if (hostMap != null && hostMap.size() > 0) { - params.put(HOST_ID, ToolUtils.getStr(hostMap.get(ID_FIELD))); - // 解除映射之前先查看主机是所对应的主机组是否映射该lun 找到直接从主机组种移除主机 - // 主机被移除主机组后,属于该主机组映射的lun直接被移除 - isUnmounted = findMappingVolumeToHostgroup(volumeIds, hostMap); - if (!isUnmounted) { - String taskId = unmountHostGetTaskId2(params); - if (!StringUtils.isEmpty(taskId)) { - taskIds.add(taskId); - } + if (params.get(HOSTIDS) != null && !"".equals(params.get(HOSTIDS))) { + hostObjIds = (List) params.get(HOSTIDS); + } + if (!StringUtils.isEmpty(ToolUtils.getStr(params.get(CLUSTER_ID)))) { + clusterObjId = ToolUtils.getStr(params.get(CLUSTER_ID)); + String hosts = vcsdkUtils.getHostsOnCluster(clusterObjId); + if (!StringUtils.isEmpty(hosts)) { + List> list = gson.fromJson(hosts, List.class); + for (Map map : list) { + String hostId = map.get(HOSTID); + hostObjIds.add(hostId); } } } - if (params.get(CLUSTER_ID) != null) { - clusterObjId = ToolUtils.getStr(params.get(CLUSTER_ID)); - // 根据cluster获取dme侧目标主机组 - Map hostGroupMappingOrientedVolume = - getHostGroupMappingOrientedVolume(clusterObjId, volumeIds); - if (hostGroupMappingOrientedVolume != null && hostGroupMappingOrientedVolume.size() > 0) { - List volumeids = new ArrayList<>(); - for (Map.Entry entry : hostGroupMappingOrientedVolume.entrySet()) { - volumeids.add(entry.getValue()); - params.put(HOST_GROUP_ID1, entry.getKey()); - params.put(VOLUME_IDS, volumeids); - String taskId = unmountHostGroupGetTaskId(params); - if (!StringUtils.isEmpty(taskId)) { - taskIds.add(taskId); - } - boolean isUnmappingHostgroup = taskService.checkTaskStatus(taskIds); - if (isUnmappingHostgroup) { - taskId = removeHostgroupGetTaskId(params); - } - if (!StringUtils.isEmpty(taskId)) { - taskIds.clear(); - taskIds.add(taskId); + } + // vcenter卸载存储 + if (params.get(DmeConstants.DATASTORENAMES) != null) { + List dataStoreNames = (List) params.get(DATASTORE_NAMES); + if (dataStoreNames != null && dataStoreNames.size() > 0) { + for (String dataStoreName : dataStoreNames) { + Map dsmap = new HashMap<>(); + dsmap.put(NAME_FIELD, dataStoreName); + if (!CollectionUtils.isEmpty(hostObjIds)) { + for (String hostId : hostObjIds) { + vcsdkUtils.unmountVmfsOnHostOrCluster(gson.toJson(dsmap), null, hostId); } - } } } } - + if (!CollectionUtils.isEmpty(hostObjIds)) { + Map> hostMap = getDmeHostByHostObjeId2(hostObjIds); + if (!CollectionUtils.isEmpty(hostMap)) { + for (Map.Entry> entry : hostMap.entrySet()) { + dmeHostIds.add(entry.getKey()); + // volume映射给主机 解除映射;volume映射给主机组 不解除映射 + } + needUnmapped = isNeedUnmapping(volumeIds, dmeHostIds); + } + } + // 解除Lun映射 List>> needUnmapped + if (!CollectionUtils.isEmpty(needUnmapped)) { + Map> unMappingVolumeParams = handleMap(needUnmapped); + Map unmap = new HashMap<>(); + for (Map.Entry> entry : unMappingVolumeParams.entrySet()) { + unmap.put(HOST_ID, entry.getKey()); + unmap.put(VOLUMEIDS, entry.getValue()); + String taskId = unmountHostGetTaskId2(unmap); + taskIds.add(taskId); + unmap.clear(); + } + } // 获取卸载的任务完成后的状态,默认超时时间10分钟 + boolean isUnmounted = true; if (taskIds.size() > 0) { isUnmounted = taskService.checkTaskStatus(taskIds); } - - // 判断是否卸载vmfs上的全部主机或集群 若是 则删除dme侧的卷,目前卸载参数中的主机/集群只支持单个,所以vmfs只挂载了一个主机或集群dme侧就直接删除卷 - boolean isDeleteFalg = false; - if (params.get(HOSTID) != null) { - for (String dsObj : dataStoreObjectIds) { - List> hosts = getHostsByStorageId2(dsObj); - if (hosts != null && hosts.size() == 1) { - // todo 此处注释代码暂时不要删除 - //volumeDelete(params); - isDeleteFalg = true; - break; - } + // 若卸载vmfs上的全部主机或集群 最后重新扫描 此步会自动删除vmfs + if (!isUnmounted) { + throw new DmeException( + "unmount volume precondition unmount host and hostGroup error(task status),taskIds:(" + gson.toJson( + taskIds) + ")!"); + } + if (isUnmounted && !CollectionUtils.isEmpty(hostObjIds)) { + for (String hostId : hostObjIds) { + vcsdkUtils.scanDataStore(null, hostId); } } - if (!isDeleteFalg && params.get(CLUSTER_ID) != null) { - for (String dsObjId : dataStoreObjectIds) { - List> hostGroups = getHostGroupsByStorageId2(dsObjId); - if (hostGroups != null && hostGroups.size() == 0) { - // todo 此处注释代码暂时不要删除 - //volumeDelete(params); - isDeleteFalg = true; - break; + } + + private List> findOrientedVolumeMapping(String volumeId) throws DmeException { + + List> response = new ArrayList<>(); + String url = DmeConstants.DME_QUERY_ONE_VOLUME.replace("{volume_id}", volumeId); + ResponseEntity entity = dmeAccessService.access(url, HttpMethod.GET, null); + if (entity.getStatusCodeValue() == HttpStatus.OK.value()) { + String body = entity.getBody(); + + if (StringUtils.isEmpty(body)) { + throw new DmeException("query oriented volume is null!{}", volumeId); + } + JsonObject volume = new JsonParser().parse(entity.getBody()).getAsJsonObject().get("volume").getAsJsonObject(); + LOG.info("query oriented volume ,{}", volume); + boolean attached = ToolUtils.jsonToBoo(volume.get("attached")); + if (!attached) { + throw new DmeException("query oriented volume attached status is unmapping!{}", volumeId); + } + JsonArray attachments = volume.get("attachments").getAsJsonArray(); + LOG.info("query oriented volume attachments,{}", attachments); + if (attachments.size() < 1) { + LOG.info("query oriented volume attachments is null!{}", volumeId); + } else { + for (JsonElement jsonElement : attachments) { + JsonObject attachmentsAsJsonObject = jsonElement.getAsJsonObject(); + Map volumeAttachments = new HashMap<>(); + volumeAttachments.put(ID_FIELD, ToolUtils.jsonToStr(attachmentsAsJsonObject.get(ID_FIELD))); + volumeAttachments.put(VOLUME_ID, ToolUtils.jsonToStr(attachmentsAsJsonObject.get(VOLUME_ID))); + volumeAttachments.put(HOST_ID, ToolUtils.jsonToStr(attachmentsAsJsonObject.get(HOST_ID))); + volumeAttachments.put("attached_at", ToolUtils.jsonToStr(attachmentsAsJsonObject.get("attached_at"))); + volumeAttachments.put("attached_host_group", ToolUtils.jsonToStr(attachmentsAsJsonObject.get("attached_host_group"))); + response.add(volumeAttachments); } } } - if (!isUnmounted) { - throw new DmeException( - "unmount volume precondition unmount host and hostGroup error(task status),taskIds:(" + gson.toJson( - taskIds) + ")!"); - } else { - // 如果是需要扫描LUN来卸载,则需要执行下面的方法,dataStoreNames - if (params.get(DmeConstants.DATASTORENAMES) != null) { - List dataStoreNames = (List) params.get(DATASTORE_NAMES); - if (dataStoreNames != null && dataStoreNames.size() > 0) { - for (String dataStoreName : dataStoreNames) { - Map dsmap = new HashMap<>(); - dsmap.put(NAME_FIELD, dataStoreName); - vcsdkUtils.unmountVmfsOnHostOrCluster(gson.toJson(dsmap), clusterObjId, hostObjId); + return response; + } + + private List>> isNeedUnmapping(List volumeIds, List dmeHostIds) throws DmeException { + // 返回需要解除映射的LunId及其对应的主机ID + List>> isNeeds = new ArrayList<>(); + Map> volumeMappedHost = new HashMap<>(); + for (String volumeId : volumeIds) { + List hostIds = new ArrayList<>(); + List> orientedVolume = findOrientedVolumeMapping(volumeId); + if (!CollectionUtils.isEmpty(orientedVolume)) { + for (Map map : orientedVolume) { + String hostId1 = ""; + String temp = ""; + String hostgroupId = map.get("attached_host_group"); + if (StringUtils.isEmpty(hostgroupId)) { + temp = map.get(HOST_ID); + } + if (!StringUtils.isEmpty(temp) && dmeHostIds.contains(temp)) { + hostId1 = temp; + } + if (!StringUtils.isEmpty(hostId1)) { + hostIds.add(hostId1); } } + if (!CollectionUtils.isEmpty(hostIds)) { + // 保留需要解除映射的LunId 及对应的主机Id + volumeMappedHost.put(volumeId, hostIds); + } } } - - // 若卸载vmfs上的全部主机或集群 最后重新扫描 此步会自动删除vmfs - if (isDeleteFalg) { - vcsdkUtils.scanDataStore(clusterObjId, hostObjId); + if (!CollectionUtils.isEmpty(volumeMappedHost)) { + isNeeds.add(volumeMappedHost); } + return isNeeds; } + private boolean findMappingVolumeToHostgroup(List volumeIds, Map hostMap) throws DmeException { boolean flag = false; Map hostOfHostgroup = new HashMap<>(); @@ -2348,7 +2465,7 @@ private boolean findMappingVolumeToHostgroup(List volumeIds, Map hostOfHostgroup) thr if (hostOfHostgroup != null && hostOfHostgroup.size() != 0) { for (Map.Entry entry : hostOfHostgroup.entrySet()) { List hostgroupIds = (List) entry.getValue(); - for (String hostgroupId :hostgroupIds) { + for (String hostgroupId : hostgroupIds) { String url = DmeConstants.PUT_REMOVE_HOST_FROM_HOSTGROUP.replace("{hostgroup_id}", hostgroupId); hostIds.add(entry.getKey()); params.put("host_ids", hostIds); params.put("sync_to_storage", true); ResponseEntity responseEntity = dmeAccessService.access(url, HttpMethod.PUT, gson.toJson(params)); - if (responseEntity.getStatusCodeValue()!=HttpStatus.OK.value()) { + if (responseEntity.getStatusCodeValue() != HttpStatus.OK.value()) { throw new DmeException("remove host from hostgroup failed!{}", - entry.getKey() + " from " + hostgroupId); + entry.getKey() + " from " + hostgroupId); } flag = isRemoveHostOfHostgroup(hostgroupId); } @@ -2386,7 +2503,7 @@ private boolean removeHostFromHostgroup(Map hostOfHostgroup) thr return flag; } - private Boolean isRemoveHostOfHostgroup(String hostgroupId) throws DmeException{ + private Boolean isRemoveHostOfHostgroup(String hostgroupId) throws DmeException { boolean flag = false; Map dmeHostGroup = dmeAccessService.getDmeHostGroup(hostgroupId); int hostCount = ToolUtils.getInt(dmeHostGroup.get("host_count")); @@ -2406,9 +2523,9 @@ private Boolean isRemoveHostOfHostgroup(String hostgroupId) throws DmeException{ private List unmountVmfsByDatastores(List dsObjIds, Map params) throws DmeException { List taskIds = new ArrayList<>(); - Map> unionmap=new HashMap<>(); - Map>> allinitionators=getAllInitionator(); - for (String dsObjId:dsObjIds) { + Map> unionmap = new HashMap<>(); + Map>> allinitionators = getAllInitionator(); + for (String dsObjId : dsObjIds) { // 获取vmfs关联的dme侧volume 并提取volumeId @@ -2448,17 +2565,16 @@ private List unmountVmfsByDatastores(List dsObjIds, Map> vcHosts = getHostsByStorageIdAllinitiators(dsObjId,allinitionators); + List> vcHosts = getHostsByStorageIdAllinitiators(dsObjId, allinitionators); if (volumeIds.size() > 0 && vcHosts != null && vcHosts.size() > 0) { - Map> hostvolumemap=unionUnmountHostFromDme(dsObjId, hostObjIds, volumeIds, vcHosts,allinitionators); - for (String temphostid:hostvolumemap.keySet()) - { - if (unionmap.get(temphostid)!=null){ - List tempvolumeids=unionmap.get(temphostid); + Map> hostvolumemap = unionUnmountHostFromDme(dsObjId, hostObjIds, volumeIds, vcHosts, allinitionators); + for (String temphostid : hostvolumemap.keySet()) { + if (unionmap.get(temphostid) != null) { + List tempvolumeids = unionmap.get(temphostid); tempvolumeids.addAll(hostvolumemap.get(temphostid)); - unionmap.put(temphostid,tempvolumeids); - }else { - unionmap.put(temphostid,hostvolumemap.get(temphostid)); + unionmap.put(temphostid, tempvolumeids); + } else { + unionmap.put(temphostid, hostvolumemap.get(temphostid)); } } } @@ -2475,7 +2591,7 @@ private List unmountVmfsByDatastores(List dsObjIds, Map tempParams = new HashMap<>(); tempParams.put(HOST_ID, temphostid); tempParams.put(VOLUMEIDS, unionmap.get(temphostid)); @@ -2490,9 +2606,216 @@ private List unmountVmfsByDatastores(List dsObjIds, Map unmountVmfsByDatastores2(Map params) throws DmeException, InterruptedException { + + List taskIds = new ArrayList<>(); + List objHostIds = new ArrayList<>(); + List dsObjIds = (List) params.get(DATASTORE_OBJECT_IDS); + Map> volumeMappedHost = new HashMap<>(); + Map> volumeMappedHostgroup = new HashMap<>(); + Map>> allinitionators = getAllInitionator(); + DmeVmwareRelation dvr = null; + for (String dsObjId : dsObjIds) { + // 获取vmfs关联的dme侧volume 并提取volumeId + List hostObjIds = new ArrayList<>(); + List volumeIds = new ArrayList<>(); + dvr = dmeVmwareRalationDao.getDmeVmwareRelationByDsId(dsObjId); + if (dvr == null) { + LOG.error("dme vmware relation table data or store id error,can not find targeted volume id!{}", dsObjId); + throw new DmeException("dme vmware relation table data or store id error,can not find targeted volume id!"); + } else { + volumeIds.add(dvr.getVolumeId()); + } + + //查找Lun映射的所有集群 + List> volumeRientedHost = findOrientedVolumeMapping(dvr.getVolumeId()); + if (!CollectionUtils.isEmpty(volumeRientedHost)) { + //存在映射的主机组 解除映射 + List hostgroupIds = new ArrayList<>(); + for (Map hostGroup : volumeRientedHost) { + String hostgroupId = hostGroup.get("attached_host_group"); + if (!StringUtils.isEmpty(hostgroupId) && !hostgroupIds.contains(hostgroupId)) { + hostgroupIds.add(hostgroupId); + } + } + if (!CollectionUtils.isEmpty(hostgroupIds)) { + volumeMappedHostgroup.put(dvr.getVolumeId(), hostgroupIds); + } + } + //查询Lun所有映射的主机(解除Lun与主机的关联) + List hostIds = new ArrayList<>(); + //List> volumeRientedHost = findOrientedVolumeMapping(dvr.getVolumeId()); + if (!CollectionUtils.isEmpty(volumeRientedHost)) { + for (Map map : volumeRientedHost) { + // 排除以主机组映射的情况 + String hostId = map.get(HOST_ID); + if (StringUtils.isEmpty(map.get("attached_host_group")) && !StringUtils.isEmpty(hostId)) { + hostIds.add(hostId); + } + } + List> vcenterHosts = new ArrayList<>(); + if (!CollectionUtils.isEmpty(hostIds)) { + vcenterHosts = checkVolumeMappedHost(dsObjId, allinitionators, hostIds); + hostIds.clear(); + } + if (!CollectionUtils.isEmpty(vcenterHosts)) { + for (Map map : vcenterHosts) { + if (!objHostIds.contains(map.get(HOST_OBJ_IDS))) { + objHostIds.add(map.get(HOST_OBJ_IDS)); + } + if (!StringUtils.isEmpty(map.get(HOSTID))) { + hostIds.add(map.get(HOSTID)); + } + } + volumeMappedHost.put(dvr.getVolumeId(), hostIds); + } + } + } + + //vcenter侧移除存储 + for (String storeId : dsObjIds) { + // vcenter侧移除存储 + if (!vcsdkUtils.deleteVmfsDataStore(storeId)) { + LOG.info("vcenter remove vmfs datastore error!", storeId); + continue; + } + } + // 解除Lun映射(主机/主机组) + if (!CollectionUtils.isEmpty(volumeMappedHostgroup)) { + unMappingLunToHostGroup(taskIds, volumeMappedHostgroup, dvr.getStorageDeviceId()); + } + if (!CollectionUtils.isEmpty(volumeMappedHost)) { + unMappingLunToHost(taskIds, volumeMappedHost); + } + + return taskIds; + } + + private List unMappingLunToHostGroup(List taskIds, Map> volumeMappedHostgroup, String storageId) throws DmeException, InterruptedException { + Map> unmappingParams = convertMap(volumeMappedHostgroup); + for (Map.Entry> entry : unmappingParams.entrySet()) { + Map map = new HashMap<>(); + map.put(HOST_GROUP_ID1, entry.getKey()); + map.put(VOLUMEIDS, entry.getValue()); + if (!CollectionUtils.isEmpty(map)) { + String taskId = unmountHostGroupGetTaskId(map); + taskIds.add(taskId); + // 等待数据同步到存储,否则映射视图没有同步 + Thread.sleep(2000); + // 满足删除主机组条件(无Lun映射)删除主机组 + Boolean isDelete = isDeleteHostgroups(storageId, entry.getKey(), HOST_GROUP_VIEW_TYPE); + if (taskService.checkTaskStatus(taskIds) && isDelete) { + removeHostgroupGetTaskId(map); + } + } + } + return taskIds; + } + + private List unMappingLunToHost(List taskIds, Map> volumeMappedHost) throws DmeException { + Map> unmappingParams = convertMap(volumeMappedHost); + Map tempParams = new HashMap<>(); + for (Map.Entry> entry : unmappingParams.entrySet()) { + tempParams.put(HOST_ID, entry.getKey()); + tempParams.put(VOLUMEIDS, entry.getValue()); + String taskId = unmountHostGetTaskId(tempParams); + taskIds.add(taskId); + } + return taskIds; + } + + + private List> checkVolumeMappedHost(String storeId, Map>> allinitionators, + List hostIds) throws DmeException { + List> hostMapList = new ArrayList<>(); + // 获取vcenter存储对应挂载的主机 + String listStr = vcsdkUtils.getHostsByDsObjectId(storeId, true); + + if (!StringUtils.isEmpty(listStr)) { + List> hosts = gson.fromJson(listStr, + new TypeToken>>() { + }.getType()); + + // vcenter侧主机启动器是否和dem侧主机启动器一致 + for (Map host : hosts) { + String objHostId = ToolUtils.getStr(host.get(HOSTID)); + String hostName = ToolUtils.getStr(host.get(HOST_NAME)); + String dmeHostId = ""; + if (!StringUtils.isEmpty(objHostId)) { + dmeHostId = checkToHostAllInitiators2(objHostId, allinitionators, hostIds); + Map tempMap = new HashMap<>(); + if (!StringUtils.isEmpty(dmeHostId)) { + tempMap.put(HOST_OBJ_IDS, objHostId); + tempMap.put(HOST_NAME, hostName); + tempMap.put(HOSTID, dmeHostId); + hostMapList.add(tempMap); + } + } + + } + } + return hostMapList; + } + + private Map> convertMap(Map> param1) { + Map> param2 = new HashMap<>(); + for (Map.Entry> entry : param1.entrySet()) { + for (String hostOrGroupId : entry.getValue()) { + if (param2.get(hostOrGroupId) == null) { + List volumeIds = new ArrayList<>(); + volumeIds.add(entry.getKey()); + param2.put(hostOrGroupId, volumeIds); + } else { + param2.get(hostOrGroupId).add(entry.getKey()); + } + } + } + return param2; + + } + + private Map> handleMap(List>> param1) { + Map> result = new HashMap<>(); + List list = new ArrayList<>(); + for (Map> map : param1) { + Map> volumeToHost = convertMap(map); + for (Map.Entry> entry : volumeToHost.entrySet()) { + if (result.get(entry.getKey()) == null) { + result.put(entry.getKey(), entry.getValue()); + } else { + for (String volumeId : entry.getValue()) { + if (!result.get(entry.getKey()).contains(volumeId)) { + result.get(entry.getKey()).add(volumeId); + } + } + } + } + } + return result; + } + + private Boolean isDeleteHostgroups(String storageId, String hostgroupId, String type) throws DmeException { + + Map params = new HashMap<>(); + params.put("type", "host_group"); + params.put("request_id", hostgroupId); + params.put("storage_id", storageId); + + ResponseEntity access = dmeAccessService.access(DmeConstants.QUERY_HOSTGROUP_MAPPING_VIEW_URL, HttpMethod.POST, gson.toJson(params)); + if (access.getStatusCodeValue() != HttpStatus.OK.value()) { + throw new DmeException(String.valueOf(access.getStatusCodeValue()), "query host group mapping view failed !"); + } + JsonArray jsonArray = new JsonParser().parse(access.getBody()).getAsJsonArray(); + if (jsonArray.size() < 1) { + return true; + } + return false; + } + + private List unmountVmfs(String dsObjId, Map params) throws DmeException { List taskIds = new ArrayList<>(); - Map>> allinitionators=getAllInitionator(); + Map>> allinitionators = getAllInitionator(); // 获取vmfs关联的dme侧volume 并提取volumeId List hostObjIds = new ArrayList<>(); List volumeIds = new ArrayList<>(); @@ -2511,7 +2834,7 @@ private List unmountVmfs(String dsObjId, Map params) thr } // 通过主机组ID,volume id 获取到要卸载的主机组 并执行卸载 Map hostGroupMappingOrientedVolume = - getHostGroupMappingOrientedVolume(hostGroupObjectId, volumeIds); + getHostGroupMappingOrientedVolume(hostGroupObjectId, volumeIds); if (hostGroupMappingOrientedVolume != null && hostGroupMappingOrientedVolume.size() != 0) { for (Map.Entry entry : hostGroupMappingOrientedVolume.entrySet()) { @@ -2532,7 +2855,7 @@ private List unmountVmfs(String dsObjId, Map params) thr // 没有指定主机 下查询datastore的主机 并过滤与vm有关联的 List> vcHosts = getHostsByStorageId2(dsObjId); if (volumeIds.size() > 0 && vcHosts != null && vcHosts.size() > 0) { - taskIds.addAll(unmountHostFromDme(dsObjId, hostObjIds, volumeIds, vcHosts,allinitionators)); + taskIds.addAll(unmountHostFromDme(dsObjId, hostObjIds, volumeIds, vcHosts, allinitionators)); } // 提取datastore的hostid @@ -2552,26 +2875,26 @@ private List unmountVmfs(String dsObjId, Map params) thr return taskIds; } - private Map> unionUnmountHostFromDme(String dsObjId, List hostObjIds, List volumeIds, - List> vcHosts,Map>> allinitiators) throws DmeException { - Map> retParams = new HashMap<>(); + private Map> unionUnmountHostFromDme(String dsObjId, List hostObjIds, List volumeIds, + List> vcHosts, Map>> allinitiators) throws DmeException { + Map> retParams = new HashMap<>(); //List taskIds = new ArrayList<>(); for (Map vcHost : vcHosts) { String hostObjectId = ToolUtils.getStr(vcHost.get(HOSTID)); if (!StringUtils.isEmpty(hostObjectId)) { - Map hostMap = getDmeHostByHostObjeId(hostObjectId,allinitiators); + Map hostMap = getDmeHostByHostObjeId(hostObjectId, allinitiators); // vcenter的host和dem的host的启动器一样 if (hostMap != null && hostMap.size() > 0) { hostObjIds.add(hostObjectId); String hostId = ToolUtils.getStr(hostMap.get(ID_FIELD)); - // 是否关联vm - if (dataStoreVmRelateHostOrCluster(dsObjId, hostObjectId, null)) { + /* // 是否关联vm + if (vcsdkUtils.hasVmOnDatastore(dsObjId)) { continue; - } - retParams.put(hostId,volumeIds); + }*/ + retParams.put(hostId, volumeIds); } } } @@ -2580,12 +2903,12 @@ private Map> unionUnmountHostFromDme(String dsObjId, List unmountHostFromDme(String dsObjId, List hostObjIds, List volumeIds, - List> vcHosts,Map>> allinitiators) throws DmeException { + List> vcHosts, Map>> allinitiators) throws DmeException { List taskIds = new ArrayList<>(); for (Map vcHost : vcHosts) { String hostObjectId = ToolUtils.getStr(vcHost.get(HOSTID)); if (!StringUtils.isEmpty(hostObjectId)) { - Map hostMap = getDmeHostByHostObjeId(hostObjectId,allinitiators); + Map hostMap = getDmeHostByHostObjeId(hostObjectId, allinitiators); // vcenter的host和dem的host的启动器一样 if (hostMap != null && hostMap.size() > 0) { @@ -2609,23 +2932,18 @@ private List unmountHostFromDme(String dsObjId, List hostObjIds, } // 删除前的卸载 - public List unmountVmfsAll(Map params) throws DmeException { + public List unmountVmfsAll(Map params) throws DmeException, InterruptedException { List taskIds = new ArrayList<>(); // 获取vmfs关联的dme侧volume 并提取volumeId if (params != null && params.get(DmeConstants.DATASTOREOBJECTIDS) != null) { List dataStoreObjectIds = (List) params.get(DATASTORE_OBJECT_IDS); List dataStorageIds = new ArrayList<>(); - if (dataStoreObjectIds != null && dataStoreObjectIds.size() > 0) { + if (!CollectionUtils.isEmpty(dataStoreObjectIds)) { List volumeIds = new ArrayList<>(); List dataStoreNames = new ArrayList<>(); + List bounds = new ArrayList<>(); for (String dsObjectId : dataStoreObjectIds) { - // 如果dsObject包含虚拟机 则不能删除 - boolean isFoundVm = vcsdkUtils.hasVmOnDatastore(dsObjectId); - if (isFoundVm) { - LOG.info("vmfs delete,the vmfs:{} contain vm,can not delete!!!", dsObjectId); - continue; - } DmeVmwareRelation dvr = null; try { dvr = dmeVmwareRalationDao.getDmeVmwareRelationByDsId(dsObjectId); @@ -2636,93 +2954,59 @@ public List unmountVmfsAll(Map params) throws DmeExcepti scanVmfs(); dvr = dmeVmwareRalationDao.getDmeVmwareRelationByDsId(dsObjectId); } + // 如果dsObject包含虚拟机 则不能删除 + boolean isFoundVm = vcsdkUtils.hasVmOnDatastore(dsObjectId); + if (isFoundVm) { + bounds.add(dvr.getStoreName()); + LOG.info("vmfs delete,the vmfs:{} contain vm,can not delete!!!", dsObjectId); + continue; + } + if (dvr != null) { volumeIds.add(dvr.getVolumeId()); dataStoreNames.add(dvr.getStoreName()); dataStorageIds.add(dsObjectId); } } - if (volumeIds.size() > 0) { + if (!CollectionUtils.isEmpty(volumeIds)) { params.put(VOLUMEIDS, volumeIds); params.put(DATASTORE_NAMES, dataStoreNames); - } - - // 没有满足条件的datastore 直接返回taskids(size=0) - if (dataStorageIds.size() == 0) { - LOG.info("vmfs delete,all vmfs contain vm,can not delete!!!"); - return taskIds; + params.put(DATASTORE_OBJECT_IDS, dataStorageIds); + }else { + throw new DmeException("the vmfs:" + bounds + " contain virtual machine,can not unmount!"); } } - - // 获取vcenter关联的所有hostId, dataStoreObjectIds只有一个值 - /*for (String dsObjectId : dataStorageIds) { - List unmountTaskIds = unmountVmfs(dsObjectId, params); - if (unmountTaskIds != null && unmountTaskIds.size() > 0) { - taskIds.addAll(unmountTaskIds); - } - }*/ - - List unmountTaskIds = unmountVmfsByDatastores(dataStorageIds, params); + // dme 侧解除关联 + List unmountTaskIds = unmountVmfsByDatastores2(params); if (unmountTaskIds != null && unmountTaskIds.size() > 0) { taskIds.addAll(unmountTaskIds); } } - return taskIds; } @Override public void deleteVmfs(Map params) throws DmeException { - // 先调卸载的接口 卸载是卸载所有所有主机和集群(dem侧主机,主机组) + // 先调卸载的接口 卸载是卸载所有所有主机和集群(dme侧主机,主机组) try { List unmountTaskIds = unmountVmfsAll(params); - if (unmountTaskIds != null && unmountTaskIds.size() > 0) { + if (!CollectionUtils.isEmpty(unmountTaskIds)) { // 检测任务等待卸载完成后再删除,不用判断是否卸载成功 taskService.checkTaskStatus(unmountTaskIds); } - } catch (DmeException e) { - LOG.error("delete volume precondition unmapping host and hostGroup error!"); - throw new DmeException("delete volume precondition unmapping host and hostGroup error!"); + } catch (DmeException | InterruptedException e) { + throw new DmeException(e.getMessage()); } - // DME侧卸载卷 - // todo 此处删除卷的功能暂时屏蔽 请不要删除 - /*String taskId = volumeDeleteGetTaskId(params); - if (!StringUtils.isEmpty(taskId)) { - boolean isDmeDelete = taskService.checkTaskStatus(Arrays.asList(taskId)); - if (!isDmeDelete) { - throw new DmeException(taskService.queryTaskById(taskId).getDetail()); - } - } else { - throw new DmeException("dme delete vmfs failed,task id is null!"); - }*/ - // vcenter侧 扫描 List hostObjIds = (List) params.get(HOST_OBJ_IDS); - if (hostObjIds != null && hostObjIds.size() > 0) { + if (!CollectionUtils.isEmpty(hostObjIds)) { // 过滤重复的hostObjId hostObjIds = new ArrayList<>(new HashSet(hostObjIds)); for (String hostObjId : hostObjIds) { vcsdkUtils.scanDataStore(null, hostObjId); } - } else { - // dme侧已删除(卸载) hostObjectIds参数为空,此时通过dsObjectId查询hostObjId,再扫描一次 - List dataStoreObjectIds = (List) params.get(DATASTORE_OBJECT_IDS); - if (dataStoreObjectIds != null && dataStoreObjectIds.size() > 0) { - for (String dsObjId : dataStoreObjectIds) { - String listStr = vcsdkUtils.getMountHostsByDsObjectId(dsObjId); - if (!StringUtils.isEmpty(listStr)) { - List> lists = gson.fromJson(listStr, - new TypeToken>>() { }.getType()); - for (Map hostMap : lists) { - String hostObjId = hostMap.get(HOSTID); - vcsdkUtils.scanDataStore(null, hostObjId); - } - } - } - } } - // 重新扫描关联关系 更新数据库 scanVmfs(); } @@ -2738,10 +3022,10 @@ private String unmountHostGetTaskId(Map params) { } return taskId; } + private String unmountHostGetTaskId2(Map params) { String taskId = ""; try { - //卸载主机之前检查对应的主机是否有主机组存在,如果有 找到目标主机组 解除映射 ResponseEntity responseEntity = hostUnmapping(params); taskId = getTaskId(responseEntity); } catch (DmeException e) { @@ -2779,7 +3063,7 @@ private ResponseEntity removeHostgroup(Map params) throws DmeExc String url = DmeConstants.HOSTGROUP_REMOVE.replace("{hostgroup_id}", hostGroupId); requestbody.put("sync_to_storage", true); ResponseEntity responseEntity = dmeAccessService.access(url, HttpMethod.DELETE, - null); + gson.toJson(requestbody)); return responseEntity; } @@ -2802,7 +3086,7 @@ private ResponseEntity hostUnmapping(Map params) throws DmeExcep requestbody.put(HOST_ID, hostId); requestbody.put(VOLUME_IDS, volumeIds); ResponseEntity responseEntity = dmeAccessService.access(DmeConstants.DME_HOST_UNMAPPING_URL, HttpMethod.POST, - gson.toJson(requestbody)); + gson.toJson(requestbody)); return responseEntity; } @@ -2813,7 +3097,7 @@ private ResponseEntity hostGroupUnmapping(Map params) throws Dme requestbody.put(HOST_GROUP_ID1, hostGroupId); requestbody.put(VOLUME_IDS, volumeIds); ResponseEntity responseEntity = dmeAccessService.access(DmeConstants.HOSTGROUP_UNMAPPING, HttpMethod.POST, - gson.toJson(requestbody)); + gson.toJson(requestbody)); return responseEntity; } @@ -2822,7 +3106,7 @@ private ResponseEntity volumeDelete(Map params) throws DmeExcept Map requestbody = new HashMap<>(); requestbody.put(VOLUME_IDS, volumeIds); ResponseEntity responseEntity = dmeAccessService.access(DmeConstants.DME_VOLUME_DELETE_URL, HttpMethod.POST, - gson.toJson(requestbody)); + gson.toJson(requestbody)); return responseEntity; } @@ -2900,7 +3184,8 @@ public List> getHostsByStorageId(String storageId) throws Dm String vmwarehosts = vcsdkUtils.getHostsOnCluster(clusterid); if (!StringUtils.isEmpty(vmwarehosts)) { List> vmwarehostlists = gson.fromJson(vmwarehosts, - new TypeToken>>() { }.getType()); + new TypeToken>>() { + }.getType()); for (Map vmwarehostmap : vmwarehostlists) { excludehostmap.put(vmwarehostmap.get(HOSTID), "true"); @@ -2909,7 +3194,8 @@ public List> getHostsByStorageId(String storageId) throws Dm } if (!StringUtils.isEmpty(listStr)) { List> hosts = gson.fromJson(listStr, - new TypeToken>>() { }.getType()); + new TypeToken>>() { + }.getType()); // vcenter侧主机启动器是否和dem侧主机启动器一致 for (Map host : hosts) { @@ -2946,7 +3232,8 @@ public List> getHostsByStorageId2(String storeId) throws Dme String vmwarehosts = vcsdkUtils.getHostsOnCluster(clusterid); if (!StringUtils.isEmpty(vmwarehosts)) { List> vmwarehostlists = gson.fromJson(vmwarehosts, - new TypeToken>>() { }.getType()); + new TypeToken>>() { + }.getType()); for (Map vmwarehostmap : vmwarehostlists) { excludehostmap.put(vmwarehostmap.get(HOSTID), "true"); @@ -2955,7 +3242,8 @@ public List> getHostsByStorageId2(String storeId) throws Dme } if (!StringUtils.isEmpty(listStr)) { List> hosts = gson.fromJson(listStr, - new TypeToken>>() { }.getType()); + new TypeToken>>() { + }.getType()); // vcenter侧主机启动器是否和dem侧主机启动器一致 for (Map host : hosts) { @@ -2977,10 +3265,10 @@ public List> getHostsByStorageId2(String storeId) throws Dme return hostMapList; } - public List> getHostsByStorageIdAllinitiators(String storeId,Map>> allinitiators) throws DmeException { + public List> getHostsByStorageIdAllinitiators(String storeId, Map>> allinitiators) throws DmeException { List> hostMapList = new ArrayList<>(DEFAULT_LEN); - Map hostinitonatormap=new HashMap<>(); + Map hostinitonatormap = new HashMap<>(); // 先查询vcenter侧的主机 String listStr = vcsdkUtils.getHostsByDsObjectId(storeId, true); @@ -2992,7 +3280,8 @@ public List> getHostsByStorageIdAllinitiators(String storeId String vmwarehosts = vcsdkUtils.getHostsOnCluster(clusterid); if (!StringUtils.isEmpty(vmwarehosts)) { List> vmwarehostlists = gson.fromJson(vmwarehosts, - new TypeToken>>() { }.getType()); + new TypeToken>>() { + }.getType()); for (Map vmwarehostmap : vmwarehostlists) { excludehostmap.put(vmwarehostmap.get(HOSTID), "true"); @@ -3001,7 +3290,8 @@ public List> getHostsByStorageIdAllinitiators(String storeId } if (!StringUtils.isEmpty(listStr)) { List> hosts = gson.fromJson(listStr, - new TypeToken>>() { }.getType()); + new TypeToken>>() { + }.getType()); // vcenter侧主机启动器是否和dem侧主机启动器一致 for (Map host : hosts) { @@ -3009,19 +3299,19 @@ public List> getHostsByStorageIdAllinitiators(String storeId // 排除已挂载在集群中的主机 if (excludehostmap.get(hostId) == null) { - String hostNmme = ToolUtils.getStr(host.get(HOST_NAME)); - String initiatorId=""; - if (hostinitonatormap.get(hostId)==null){ - initiatorId = checkToHostAllInitiators(hostId,allinitiators); - hostinitonatormap.put(hostId,initiatorId); - }else { + String hostName = ToolUtils.getStr(host.get(HOST_NAME)); + String initiatorId = ""; + if (hostinitonatormap.get(hostId) == null) { + initiatorId = checkToHostAllInitiators(hostId, allinitiators); + hostinitonatormap.put(hostId, initiatorId); + } else { initiatorId = hostinitonatormap.get(hostId); } if (!StringUtils.isEmpty(initiatorId)) { Map tempMap = new HashMap<>(); tempMap.put(HOSTID, hostId); - tempMap.put(HOST_NAME, hostNmme); + tempMap.put(HOST_NAME, hostName); hostMapList.add(tempMap); } } @@ -3030,6 +3320,7 @@ public List> getHostsByStorageIdAllinitiators(String storeId return hostMapList; } + @Override public List> getHostGroupsByStorageId(String storageId) throws DmeException { List> hostGroupMapList = new ArrayList<>(); @@ -3048,7 +3339,8 @@ public List> getHostGroupsByStorageId(String storageId) thro String listStr = vcsdkUtils.getMountClustersByDsObjectId(storageId, mappeddmegroups); if (!StringUtils.isEmpty(listStr)) { List> clusters = gson.fromJson(listStr, - new TypeToken>>() { }.getType()); + new TypeToken>>() { + }.getType()); // vcenter侧主机启动器是否和dem侧主机启动器一致 for (Map cluster : clusters) { @@ -3075,6 +3367,7 @@ public List> getHostGroupsByStorageId2(String storeId) throw if (dvr == null) { throw new DmeException("存储关联关系为空"); } + // DME 主机组 List hostgroupids = getDmeAttachHostGroupByVolumeId(dvr.getVolumeId()); Map mappeddmegroups = new HashMap<>(); for (String hostgroupid : hostgroupids) { @@ -3084,7 +3377,8 @@ public List> getHostGroupsByStorageId2(String storeId) throw String listStr = vcsdkUtils.getMountClustersByDsObjectId(storeId, mappeddmegroups); if (!StringUtils.isEmpty(listStr)) { List> clusters = gson.fromJson(listStr, - new TypeToken>>() { }.getType()); + new TypeToken>>() { + }.getType()); // 通过名字判断主机组是否一致 for (Map cluster : clusters) { @@ -3092,9 +3386,9 @@ public List> getHostGroupsByStorageId2(String storeId) throw String clusterNmme = ToolUtils.getStr(cluster.get("clusterName")); List volumeIds = new ArrayList<>(); volumeIds.add(dvr.getVolumeId()); - Map hostGroupMappingOrientedVolume = - getHostGroupMappingOrientedVolume(clusterId, volumeIds); - if (hostGroupMappingOrientedVolume.size()!=0) { + /*Map hostGroupMappingOrientedVolume = + getHostGroupMappingOrientedVolume(clusterId, volumeIds);*/ + if (hostgroupids.size() != 0) { Map tempMap = new HashMap<>(); tempMap.put(HOST_GROUP_ID, clusterId); tempMap.put("hostGroupName", clusterNmme); @@ -3105,6 +3399,18 @@ public List> getHostGroupsByStorageId2(String storeId) throw return hostGroupMapList; } + private List> getHostgroupsByVolumeId(String volumeId) throws DmeException { + List> hostGroupIds = new ArrayList<>(); + List hostgroupids = getDmeAttachHostGroupByVolumeId(volumeId); + for (String hostgroupid : hostgroupids) { + Map mappeddmegroups = new HashMap<>(); + Map hostgroupmap = dmeAccessService.getDmeHostGroup(hostgroupid); + mappeddmegroups.put(String.valueOf(hostgroupmap.get(ID_FIELD)), String.valueOf(hostgroupmap.get(NAME_FIELD))); + hostGroupIds.add(mappeddmegroups); + } + return hostGroupIds; + } + private List getDmeAttachHostGroupByVolumeId(String volumeId) throws DmeException { String url; List groupids = new ArrayList<>(); @@ -3130,7 +3436,7 @@ private List getDmeAttachHostGroupByVolumeId(String volumeId) throws Dme } // 通过vcenter的主机ID 查询dme侧的主机信息 - private Map getDmeHostByHostObjeId(String hostObjId,Map>> allinitiators) throws DmeException { + private Map getDmeHostByHostObjeId(String hostObjId, Map>> allinitiators) throws DmeException { Map hostInfo = new HashMap<>(); Map hbaMap = vcsdkUtils.getHbaByHostObjectId(hostObjId); if (hbaMap == null || hbaMap.size() == 0) { @@ -3150,7 +3456,7 @@ private Map getDmeHostByHostObjeId(String hostObjId,Map> initiators = dmeAccessService.getDmeHostInitiators(demHostId); - List> initiators=allinitiators.get(demHostId); + List> initiators = allinitiators.get(demHostId); if (initiators != null && initiators.size() > 0) { for (Map inimap : initiators) { String portName = ToolUtils.getStr(inimap.get(PORT_NAME)); @@ -3171,43 +3477,40 @@ private Map getDmeHostByHostObjeId(String hostObjId,Map getDmeHostByHostObjeId2(String hostObjId) throws DmeException { - Map hostInfo = new HashMap<>(); - Map hbaMap = vcsdkUtils.getHbaByHostObjectId(hostObjId); - if (hbaMap == null || hbaMap.size() == 0) { - return hostInfo; - } - String initiatorName = ToolUtils.getStr(hbaMap.get(NAME_FIELD)); - - // 取出DME所有主机 - List> hostlist = dmeAccessService.getDmeHosts2(null); - if (hostlist == null || hostlist.size() == 0) { - return hostInfo; - } - for (Map hostmap : hostlist) { - if (hostmap != null && hostmap.get(ID_FIELD) != null) { - // 通过主机ID查到对应的主机的启动器 - String demHostId = ToolUtils.getStr(hostmap.get(ID_FIELD)); + private Map> getDmeHostByHostObjeId2(List hostObjIds) throws DmeException { - // 得到主机的启动器 - List> initiators = dmeAccessService.getDmeHostInitiators(demHostId); - if (initiators != null && initiators.size() > 0) { - for (Map inimap : initiators) { - String portName = ToolUtils.getStr(inimap.get(PORT_NAME)); - if (initiatorName.equals(portName)) { - hostInfo = hostmap; - break; - } + Map hostInfo = new HashMap<>(); + Map> hostMap = new HashMap<>(); + // 查询所有启动器 + Map>> allinitionators = getAllInitionator(); + if (CollectionUtils.isEmpty(allinitionators)) { + return hostMap; + } + for (String hostObjId : hostObjIds) { + Map hbaMap = new HashMap<>(); + hbaMap = vcsdkUtils.getHbaByHostObjectId(hostObjId); + if (CollectionUtils.isEmpty(hbaMap)) { + LOG.error("query host hba is null!{}", hostObjId); + continue; + } + String initiatorName = ToolUtils.getStr(hbaMap.get(NAME_FIELD)); + for (Map.Entry>> entry : allinitionators.entrySet()) { + String dmehostId = ""; + for (Map map : entry.getValue()) { + String portName = ToolUtils.getStr(map.get(PORT_NAME)); + if (initiatorName.equalsIgnoreCase(portName)) { + hostInfo = map; + dmehostId = entry.getKey(); + break; } } - } - - // 如果已经找到的主机就不再循环 - if (hostInfo.size() > 0) { - break; + if (!StringUtils.isEmpty(dmehostId)) { + hostMap.put(dmehostId, hostInfo); + break; + } } } - return hostInfo; + return hostMap; } public boolean isVmfs(String objectId) throws DmeSqlException { @@ -3285,7 +3588,7 @@ public List queryVmfs(String dsObjId) throws Exception { } private void getVolumeDetail(List relists, Map stoNameMap, VmfsDataInfo vmfsDataInfo, - String volumeId) { + String volumeId) { String detailedVolumeUrl = DmeConstants.DME_VOLUME_BASE_URL + FIEL_SEPARATOR + volumeId; try { ResponseEntity responseEntity = dmeAccessService.access(detailedVolumeUrl, HttpMethod.GET, null); @@ -3342,4 +3645,2273 @@ private String getStorageModelByWwn(String wwn) throws DmeSqlException { return dmeVmwareRalationDao.getStorageModelByWwn(wwn); } + + // ________________________________________________________________________________________________________________________________________________________________________________ + + /** + * @throws DmeException + * @Description: 创建Vmfs, 支持多主机,多集群,集群和主机的搭配创建 + * @author yc + * @Date 2021/5/13 17:23 + */ + @Override + public CreateVmfsResponse createVmfsNew(Map params) throws DmeException { + //1.参数准备 + if (CollectionUtils.isEmpty(params)) { + throw new DmeException("create vmfs params is null"); + } + //根据前端入参判断前端选择的创建方式 + Object ss = params.get(CHOOSEDEVICE); + if (StringUtils.isEmpty(params.get(CHOOSEDEVICE))) { + throw new DmeException("create vmfs the params is error"); + } + // 根据服务等级ID获取对应的存储设备ID + Object storageId = params.get(STORAGE_ID); + if (StringUtils.isEmpty(storageId) && params.get(DmeConstants.SERVICELEVELID) != null) { + storageId = + dmeStorageService.getStorageByServiceLevelId(String.valueOf(params.get(DmeConstants.SERVICELEVELID))); + params.put(STORAGE_ID, storageId); + } + List> chooseDevicelists = gson.fromJson(gson.toJsonTree(ss), + new TypeToken>>() { + }.getType()); + //获取vmfs的创建方式 + HashSet deviceTypeSet = getDeviceTypeSet(chooseDevicelists); + //获取启动器 + List connectionFailList = new ArrayList<>(); + int failnum = 0; + int successnum = 0; + String descriptionEN = null; + String descriptionCN = null; + //todo 将主机创建和主机组的创建独立开来,针对于主机,创建vmfs之前进行联通性校验,校验通过的继续,不通过的返回不通过的主机名称和状态 + //2.1根据主机创建vmfs + if (deviceTypeSet.contains("host")) { + //a.首先检测主机的联通性 + Map>> allinitionators = getAllInitionator(); + Map> hostStatusMap = checkHostNew(params, allinitionators, chooseDevicelists); + //b.组装检测联通性失败的主机信息 + if (!CollectionUtils.isEmpty(hostStatusMap.get("failHost"))) { + hostStatusMap.get("failHost").forEach(hostid -> { + String hostname = getDmeHostNameByIdNew(hostid); + connectionFailList.add(hostname); + }); + } + if (CollectionUtils.isEmpty(hostStatusMap.get("nomalHost"))) { + throw new DmeException("DME create vmfs volume fail(all connection of hosts is lossing)!"); + } + //c.创建Lun + String taskId = createLun(params); + if (StringUtils.isEmpty(taskId)) { + throw new DmeException("create vmfs error,taskid is empty"); + } + //d.根据任务id判断创建Lun的任务状态 + TasksResultObject tasksResult = taskService.checkTaskStatusNew(taskId, longTaskTimeOut); + LOG.info("create vms isCreated" + tasksResult.toString()); + if (StringUtils.isEmpty(tasksResult)) { + throw new DmeException("DME create vmfs volume error(task status is failure)!"); + } + //e.获取卷数据信息集合 + List> volumelist = getVolumeByName(ToolUtils.getStr(params.get(VOLUMENAME)), + null, null, ToolUtils.getStr(params.get(SERVICE_LEVEL_ID)), + ToolUtils.getStr(params.get(STORAGE_ID)), ToolUtils.getStr(params.get(POOL_RAW_ID))); + LOG.info("create vms volumelist size=" + volumelist.size()); + //f.映射主机 + List volumeIdList = new ArrayList<>(); + volumelist.forEach(volumeMap -> { + volumeIdList.add(ToolUtils.getStr(volumeMap.get("volume_id"))); + }); + //TODO 将lun映射给主机的时候,接口支持将多个lun映射给同一台主机,这样就会出现一个争议(如果部分成功这个失败的lun就不能删除),如果单个循环lun去映射单个主机,就会出现批量创建时的效率问题 + // (最后的结论,多个lun映射给多个主机,一个不成功直接认为隐射失败) + List objHostIds = hostStatusMap.get("nomalHost"); + Map> mappingResultMap = lunMappingToHostOrHostgroupNew(volumeIdList, objHostIds, null); + //检查映射结果,如果该lun未映射给全部主机,直接认为隐射直接删除lun + if (!CollectionUtils.isEmpty(mappingResultMap.get("hostUnmapped"))) { + rollBackHostNew(volumeIdList, objHostIds, null, true, true); + failnum = volumeIdList.size(); + if (!CollectionUtils.isEmpty(mappingResultMap.get("descriptionEN"))) { + descriptionEN = mappingResultMap.get("descriptionEN").get(0); + } + if (!CollectionUtils.isEmpty(mappingResultMap.get("descriptionCN"))) { + descriptionCN = mappingResultMap.get("descriptionCN").get(0); + } + } else { + createOnVmware2New(params, volumelist); + successnum = volumeIdList.size(); + } + } + //2.2根据集群创建vmfs + if (deviceTypeSet.contains("cluster")) { + //a. 首先获取前端入参判断主机组是否已经存在,不存在就创建新的主机组,并且校验其联通性 + Map> maps = checkOrCreateToHostGroupNew(params, chooseDevicelists); + //b. 如果集合为空,联通性校验失败,直接抛出异常 + if (CollectionUtils.isEmpty(maps)) { + throw new DmeException("check connectivity of hostgroup is error"); + } + //c. 创建lun + String taskId = createLun(params); + if (StringUtils.isEmpty(taskId)) { + throw new DmeException("create vmfs error,taskid is empty"); + } + //d.根据任务id判断创建Lun的任务状态 + TasksResultObject tasksResult = taskService.checkTaskStatusNew(taskId, longTaskTimeOut); + LOG.info("create vms isCreated" + tasksResult.toString()); + if (StringUtils.isEmpty(tasksResult)) { + throw new DmeException("DME create vmfs volume error(task status is failure)!"); + } + //e.获取卷数据信息集合 + List> volumelist = getVolumeByName(ToolUtils.getStr(params.get(VOLUMENAME)), + null, null, ToolUtils.getStr(params.get(SERVICE_LEVEL_ID)), + ToolUtils.getStr(params.get(STORAGE_ID)), ToolUtils.getStr(params.get(POOL_RAW_ID))); + LOG.info("create vms volumelist size=" + volumelist.size()); + //f.将创建的lun映射给主机组 + List volumeIdList = new ArrayList<>(); + volumelist.forEach(volumeMap -> { + volumeIdList.add(ToolUtils.getStr(volumeMap.get("volume_id"))); + }); + List hostGroupIds = maps.get("nomalCluster"); + String createFlag = maps.get("flag").get(0); + boolean isCreate; + if (createFlag.equalsIgnoreCase("0")) { + isCreate = false; + } else { + isCreate = false; + } + Map> mappingResultMap = lunMappingToHostOrHostgroupNew(volumeIdList, null, hostGroupIds); + //g. 检查隐射结果,如果隐射失败,直接删除lun + //检查映射结果,如果该lun未映射给全部主机,直接认为隐射直接删除lun + if (!CollectionUtils.isEmpty(mappingResultMap.get("clusterUnmapped"))) { + rollBackHostNew(volumeIdList, null, hostGroupIds, isCreate, true); + failnum = volumeIdList.size(); + if (!CollectionUtils.isEmpty(mappingResultMap.get("descriptionEN"))) { + descriptionEN = mappingResultMap.get("descriptionEN").get(0); + } + if (!CollectionUtils.isEmpty(mappingResultMap.get("descriptionCN"))) { + descriptionCN = mappingResultMap.get("descriptionCN").get(0); + } + } else { + //h. 创建创建数据存储= + createOnVmware2New(params, volumelist); + successnum = volumeIdList.size(); + } + } + return new CreateVmfsResponse(successnum, failnum, connectionFailList, descriptionEN, descriptionCN); + } + + /** + * @throws DmeException + * @Description: 检验主机是否属于多个主机组, + * @Param chooseDevicelists + * @author yc + * @Date 2021/5/20 16:39 + */ + private void checkHostsBelongOnecluster(List> chooseDevicelists) throws DmeException { + //首先获取主机列表 + try { + Map hostObjectIdMap = getHostNameAndHostIdList(chooseDevicelists); + List hostIds = new ArrayList<>(hostObjectIdMap.keySet()); + HashSet clusterSet = new HashSet<>(getClusterIdsByHostId(hostIds)); + if (!CollectionUtils.isEmpty(clusterSet) && clusterSet.size() > 1) { + throw new DmeException("create vmfs error: not accept more cluster the host in"); + } + } catch (Exception e) { + throw new DmeException(e.getMessage()); + } + } + + /** + * @return deviceTypeSet + * @throws DmeException + * @Description: 根据前端入参判断前端选择的创建VFMS的组合方式 + * @Param Map params + * @author yc + * @Date 2021/5/13 14:52 + */ + private HashSet getDeviceTypeSet(List> chooseDevicelists) throws DmeException { + HashSet deviceTypeSet = new HashSet(); + if (!CollectionUtils.isEmpty(chooseDevicelists)) { + deviceTypeSet = getDeviceType(chooseDevicelists); + } + if (CollectionUtils.isEmpty(deviceTypeSet) || deviceTypeSet.size() > 1) { + throw new DmeException("create vmfs params is error"); + } + return deviceTypeSet; + } + + /** + * @return deviceTypeSet + * @throws DmeException + * @Description: 根据前端入参判断前端选择的创建VFMS的组合方式 + * @Param Map params + * @author yc + * @Date 2021/5/13 14:52 + */ + private HashSet getDeviceTypeSet2(List> chooseDevicelists) throws DmeException { + HashSet deviceTypeSet = new HashSet(); + if (!CollectionUtils.isEmpty(chooseDevicelists)) { + deviceTypeSet = getDeviceType(chooseDevicelists); + } + if (CollectionUtils.isEmpty(deviceTypeSet) || deviceTypeSet.size() > 2) { + throw new DmeException("create vmfs params is error"); + } + return deviceTypeSet; + } + + /** + * @return hostName + * @throws DmeException + * @Description: 根据主机id获取主机名称 + * @Param hostId + * @author yc + * @Date 2021/5/28 11:33 + */ + private String getDmeHostNameByIdNew(String hostId) { + String hostName = ""; + ResponseEntity responseEntity; + String getHostUrl = DmeConstants.GET_DME_HOST_URL.replace("{host_id}", hostId); + try { + responseEntity = dmeAccessService.access(getHostUrl, HttpMethod.GET, null); + } catch (Exception e) { + LOG.error("request of getDmeHostNameByIdNew time out"); + return hostName; + } + if (responseEntity.getStatusCodeValue() == RestUtils.RES_STATE_I_200) { + JsonObject vjson = new JsonParser().parse(responseEntity.getBody().toString()).getAsJsonObject(); + hostName = ToolUtils.jsonToStr(vjson.get(NAME_FIELD)); + } + return hostName; + } + + /** + * @return @return + * @throws + * @Description: 回滚函数 + * @Param @param null + * @author yc + * @Date 2021/5/13 17:22 + */ + private void rollBackHostNew(List volumeIds, List dmeHostIds, List demHostGroupIds, + Boolean isCreated, Boolean isMapping) throws DmeException { + ResponseEntity responseEntity = null; + String taskId = ""; + if (!CollectionUtils.isEmpty(volumeIds)) { + Map requestParam = new HashMap<>(); + //解除映射,删除已创建的卷 + requestParam.put(VOLUMEIDS, volumeIds); + if (isMapping) { + if (!CollectionUtils.isEmpty(dmeHostIds)) { + for (String dmeHostId : dmeHostIds) { + requestParam.put(HOST_ID, dmeHostId); + responseEntity = hostUnmapping(requestParam); + } + } + if (!CollectionUtils.isEmpty(demHostGroupIds)) { + for (String demHostGroupId : demHostGroupIds) { + requestParam.put(HOST_GROUP_ID1, demHostGroupId); + responseEntity = hostGroupUnmapping(requestParam); + } + } + if (responseEntity.getStatusCodeValue() == HttpStatus.ACCEPTED.value()) { + taskId = ToolUtils.jsonToStr( + new JsonParser().parse(ToolUtils.getStr(responseEntity.getBody())).getAsJsonObject() + .get("task_id")); + } + } + Set taskIds = new HashSet<>(); + taskIds.add(taskId); + if (taskId.equals("") || taskService.checkTaskStatusLarge(taskIds, longTaskTimeOut)) { + volumeDelete(requestParam); + if (!CollectionUtils.isEmpty(demHostGroupIds) && isCreated) { + for (String demHostGroupId : demHostGroupIds) { + deleteHostgroup(demHostGroupId); + } + } + } + } + } + + /** + * @throws DmeException + * @Description: 在虚拟机上创建存储 + * @Param params, volumemaps + * @author yc + * @Date 2021/5/31 16:10 + */ + private void createOnVmware2New(Map params, List> volumemaps) throws DmeException { + VCenterInfo vcenterinfo = null; + if (!StringUtils.isEmpty(params.get(DmeConstants.SERVICELEVELID))) { + vcenterinfo = vcenterinfoservice.getVcenterInfo(); + } + final VCenterInfo vcentertemp = vcenterinfo; + //创建前先扫描hba,避免每次循环扫描 + Object ss = params.get(CHOOSEDEVICE); + + List> chooseDevicelists = gson.fromJson(gson.toJsonTree(ss), + new TypeToken>>() { + }.getType()); + //获取主机信息 + Map hostObjectIdMap = getHostNameAndHostIdList(chooseDevicelists); + Set hostObjectIds = hostObjectIdMap.keySet(); + //获取集群信息 + List clusterObjectIds = getClusterIdList(chooseDevicelists); + if (!CollectionUtils.isEmpty(hostObjectIds)) { + for (String hostObjectId : hostObjectIds) { + vcsdkUtils.rescanHbaByHostObjectId(hostObjectId); + } + } + if (!CollectionUtils.isEmpty(clusterObjectIds)) { + for (String clusterObjectId : clusterObjectIds) { + vcsdkUtils.rescanHbaByClusterObjectId(clusterObjectId); + } + } + Map paramstemp = new HashMap<>(params); + for (Map volumemap : volumemaps) { + + try { + // 创建vmware中的vmfs存储。 + paramstemp.put(VOLUME_WWN, volumemap.get(VOLUME_WWN)); + paramstemp.put(VOLUME_NAME, volumemap.get(VOLUME_NAME)); + String dataStoreStr = createVmfsOnVmwareNew(paramstemp, hostObjectIdMap, clusterObjectIds); + if (!StringUtils.isEmpty(dataStoreStr)) { + Map dataStoreMap = gson.fromJson(dataStoreStr, + new TypeToken>() { + }.getType()); + if (dataStoreMap != null) { + // 将DME卷与vmfs的关系保存数据库,因为可以同时创建几个卷,无法在此得到对应关系,所以此处不再保存关系信息 + saveDmeVmwareRalation(volumemap, dataStoreMap); + // 关联服务等级 + if (!StringUtils.isEmpty(paramstemp.get(SERVICE_LEVEL_ID))) { + String serviceLevelName = ToolUtils.getStr(paramstemp.get(SERVICE_LEVEL_NAME)); + vcsdkUtils.attachTag(ToolUtils.getStr(dataStoreMap.get(TYPE)), + ToolUtils.getStr(dataStoreMap.get(ID_FIELD)), serviceLevelName, vcentertemp); + } + } + //将vmfs挂载到其他主机上 + if (hostObjectIds.size() > 1) { + mountVmfsOnVmwareNew(params, chooseDevicelists); + } + } else { + throw new DmeException("vmware create vmfs error:" + params.get(VOLUME_NAME)); + } + + } catch (Exception e) { + LOG.info("vmware create vmfs error:" + params.get(VOLUME_NAME)); + } + } + } + + /** + * @return Map> + * @throws DmeException + * @Description: 检查主机组是否存在,不存在就创建主机组 + * @Param params, deviceTypeSet, chooseDevicelists + * @author yc + * @Date 2021/6/1 15:19 + */ + private Map> checkOrCreateToHostGroupNew(Map params, + List> chooseDevicelists) throws DmeException { + //去重后根据前端入参的方式进行逻辑判断 + Map> hostIds = new HashMap<>(); + int createFlag = 0; + try { + //单纯选择主机组的方式创建 + //todo 重新改造原有方法(检查主机组连通性) + //检查主机组是否存在,不存在就创建新的主机组 + List clusters = getClusterIdList(chooseDevicelists); + if (!CollectionUtils.isEmpty(clusters) && clusters.size() > 1) { + throw new DmeException("create vmfs params is error"); + } + //校验主机组是否存在,存在,先检查连通性进行映射,不存在就创建新的主机组再进行隐射 + HostGroupAndClusterConsistency checkResult = checkConsistencyAndGetclusterId(clusters.get(0),null); + String hostGroupId = null; + if (!StringUtils.isEmpty(checkResult) && !StringUtils.isEmpty(checkResult.getHostGroupId())) { + hostGroupId = checkResult.getHostGroupId(); + } else { + //需要创建主机组 + List objIds = createHostGroupIdNew(clusters,null); + createFlag = 1; + if (!CollectionUtils.isEmpty(objIds)) { + hostGroupId = objIds.get(0); + } + } + List failGroupHostIdList = new ArrayList<>(); + // 检查主机组连通性 + if (!StringUtils.isEmpty(hostGroupId)) { + failGroupHostIdList.addAll(estimateConnectivityOfHostOrHostgroupNew(ToolUtils.getStr(params.get(STORAGE_ID)), null, hostGroupId)); + } + if (CollectionUtils.isEmpty(failGroupHostIdList)) { + hostIds.put("nomalCluster", Arrays.asList(hostGroupId)); + } + hostIds.put("flag", Arrays.asList(Integer.toString(createFlag))); + } catch (DmeException e) { + LOG.error("checkOrcreateToHostorHostGroup error:", e); + throw new DmeException(e.getMessage()); + } + return hostIds; + } + /** + * @return Map> + * @throws DmeException + * @Description: 检查主机组是否存在,不存在就创建主机组 + * @Param params, deviceTypeSet, chooseDevicelists + * @author yc + * @Date 2021/6/1 15:19 + */ + private List>> checkOrCreateToHostGroupNew2(Map params, + + List> chooseDevicelists, + String hostGroupVolumid) throws DmeException { + List>> temps = new ArrayList<>(); + if(StringUtils.isEmpty(hostGroupVolumid)){ + throw new DmeException("mount vmfs params is error"); + } + //去重后根据前端入参的方式进行逻辑判断 + int createFlag = 0; + try { + //单纯选择主机组的方式创建 + //todo 重新改造原有方法(检查主机组连通性) + //检查主机组是否存在,不存在就创建新的主机组 + List clusters = getClusterIdList(chooseDevicelists); + if (CollectionUtils.isEmpty(clusters)) { + throw new DmeException("mount vmfs params is error"); + } + //校验主机组是否存在,存在,先检查连通性进行映射,不存在就创建新的主机组再进行隐射 + for (String clusterid : clusters) { + Map> hostIds = new HashMap<>(); + HostGroupAndClusterConsistency checkResult = checkConsistencyAndGetclusterId(clusterid,hostGroupVolumid); + String hostGroupId = null; + if (!StringUtils.isEmpty(checkResult) && !StringUtils.isEmpty(checkResult.getHostGroupId())) { + hostGroupId = checkResult.getHostGroupId(); + } else { + //需要创建主机组 + List objIds = createHostGroupIdNew(Arrays.asList(clusterid),hostGroupVolumid); + createFlag = 1; + if (!CollectionUtils.isEmpty(objIds)) { + hostGroupId = objIds.get(0); + } + } + List failGroupHostIdList = new ArrayList<>(); + // 检查主机组连通性 + if (!StringUtils.isEmpty(hostGroupId)) { + failGroupHostIdList.addAll(estimateConnectivityOfHostOrHostgroupNew(ToolUtils.getStr(params.get(STORAGE_ID)), null, hostGroupId)); + } + if (CollectionUtils.isEmpty(failGroupHostIdList)) { + hostIds.put("nomalCluster", Arrays.asList(hostGroupId)); + } + hostIds.put("flag", Arrays.asList(Integer.toString(createFlag))); + temps.add(hostIds); + } + } catch (DmeException e) { + LOG.error("checkOrcreateToHostorHostGroup error:", e); + throw new DmeException(e.getMessage()); + } + return temps; + } + /** + * @throws DmeException + * @Description: 检验主机是否属于多个主机组, + * @Param chooseDevicelists + * @author yc + * @Date 2021/5/20 16:39 + */ + public List getClusterIdsByHostId(List hostIds) throws VcenterException { + //首先判断入参 + ArrayList clusterIds = new ArrayList(); + if (CollectionUtils.isEmpty(hostIds)) + return clusterIds; + List clusteridList = vcsdkUtils.getAllClusterIds(); + //循环主机id,判断主机所属的主机组 + for (String hostid : hostIds) { + for (String clusterid : clusteridList) { + List hosts = vcsdkUtils.getHostidsOnCluster(clusterid); + if (!CollectionUtils.isEmpty(hosts) && hosts.contains(hostid)) { + clusterIds.add(clusterid); + } + } + } + return clusterIds; + } + + + /** + * @return deviceTypeSet + * @Description: 根据前端入参判断用户选择是通过主机方式创建还是根据主机组方式创建,或者进行混合创建 + * @Param chooseDevicelists + * @author yc + * @Date 2021/5/12 11:44 + */ + private HashSet getDeviceType(List> chooseDevicelists) { + HashSet deviceTypeSet = new HashSet(); + for (Map chooseMap : chooseDevicelists) { + deviceTypeSet.add(StringUtils.trimAllWhitespace(chooseMap.get("deviceType"))); + } + return deviceTypeSet; + } + + /** + * @Description: 获取参数中的主机名称和Id列表 + * @Param params + * @author yc + * @Date 2021/5/12 14:37 + */ + private Map getHostNameAndHostIdList(List> chooseDevicelists) { + HashMap hostMap = new HashMap(); + for (Map chooseMap : chooseDevicelists) { + if ("host".equalsIgnoreCase(StringUtils.trimAllWhitespace(chooseMap.get("deviceType")))) { + hostMap.put(StringUtils.trimAllWhitespace(chooseMap.get("deviceId")), StringUtils.trimAllWhitespace(chooseMap.get("deviceName"))); + } + } + return hostMap; + + } + + /** + * @Description: 获取参数中的主机组id列表 + * @Param params + * @author yc + * @Date 2021/5/12 14:39 + */ + private List getClusterIdList(List> chooseDevicelists) { + ArrayList clusterList = new ArrayList(); + for (Map chooseMap : chooseDevicelists) { + if ("cluster".equalsIgnoreCase(StringUtils.trimAllWhitespace(chooseMap.get("deviceType")))) { + clusterList.add(StringUtils.trimAllWhitespace(chooseMap.get("deviceId"))); + } + } + return clusterList; + } + + /** + * @return hostIds + * @throws DmeException + * @Description: 检查主机或者主机是否存在,不存在就创建新的主机 + * @Param params, allinitionators, volumeId, deviceTypeSet + * @author yc + * @Date 2021/5/13 14:54 + */ + private Map> checkHostNew(Map params, + Map>> allinitionators, + List> chooseDevicelists) throws DmeException { + List hostIdList = new ArrayList<>(); + Map> hostIds = new HashMap<>(); + + try { + //检查以主机的方式创建,多主机是否属于同一主机组,不支持多主机组的形式 + if (chooseDevicelists.size() > 1) { + checkHostsBelongOnecluster(chooseDevicelists); + } + //检查主机是否存在,不存在就创建新的主机 + Map hostIdMaps = getHostNameAndHostIdList(chooseDevicelists); + List objIds = checkOrCreateToHostNew(hostIdMaps, allinitionators); + // 根据获取到的dme主机,检查主机连通性结果,返回联通性异常的主机 + hostIdList = estimateConnectivityOfHostOrHostgroupNew(ToolUtils.getStr(params.get(STORAGE_ID)), objIds, null); + // 连通性正常的主机id + if (!CollectionUtils.isEmpty(hostIdList)) { + hostIds.put("failHost", hostIdList); + objIds.removeAll(hostIdList); + } + hostIds.put("nomalHost", objIds); + } catch (DmeException e) { + LOG.error("checkOrcreateToHostorHostGroup error:", e); + throw new DmeException(e.getMessage()); + } + return hostIds; + } + /** + * @return hostIds + * @throws DmeException + * @Description: 检查主机或者主机是否存在,不存在就创建新的主机 + * @Param params, allinitionators, volumeId, deviceTypeSet + * @author yc + * @Date 2021/5/13 14:54 + */ + private Map> checkHostNewNoCheckCluster(Map params, + Map>> allinitionators, + List> chooseDevicelists) throws DmeException { + List hostIdList = new ArrayList<>(); + Map> hostIds = new HashMap<>(); + + try { + //检查主机是否存在,不存在就创建新的主机 + Map hostIdMaps = getHostNameAndHostIdList(chooseDevicelists); + List objIds = checkOrCreateToHostNew(hostIdMaps, allinitionators); + // 根据获取到的dme主机,检查主机连通性结果,返回联通性异常的主机 + hostIdList = estimateConnectivityOfHostOrHostgroupNew(ToolUtils.getStr(params.get(STORAGE_ID)), objIds, null); + // 连通性正常的主机id + if (!CollectionUtils.isEmpty(hostIdList)) { + hostIds.put("failHost", hostIdList); + objIds.removeAll(hostIdList); + } + hostIds.put("nomalHost", objIds); + } catch (DmeException e) { + LOG.error("checkOrcreateToHostorHostGroup error:", e); + throw new DmeException(e.getMessage()); + } + return hostIds; + } + /** + * @Description: 检查主机是否存在,不存在就创建新的主机 + * @author yc + * @Date 2021/5/12 14:55 + */ + private List checkOrCreateToHostNew(Map hostNameAndHostIdList, + Map>> allinitionators) throws DmeException { + ArrayList objIds = new ArrayList(); + if (CollectionUtils.isEmpty(hostNameAndHostIdList)) { + return null; + } + Set hostIds = hostNameAndHostIdList.keySet(); + try { + //获取各个主机的适配器集合 + for (String hostId : hostIds) { + String objId = ""; + List> hbas = vcsdkUtils.getHbasByHostObjectId(hostId); + if (CollectionUtils.isEmpty(hbas)) { + throw new DmeException("The" + hostNameAndHostIdList.get(hostId) + " did not find a valid Hba"); + } + List wwniqns = new ArrayList<>(); + for (Map hba : hbas) { + wwniqns.add(ToolUtils.getStr(hba.get(NAME_FIELD))); + } + for (String dmehostid : allinitionators.keySet()) { + List> hostinitionators = allinitionators.get(dmehostid); + if (hostinitionators != null && hostinitionators.size() > 0) { + for (Map inimap : hostinitionators) { + String portName = ToolUtils.getStr(inimap.get(PORT_NAME)); + if (wwniqns.contains(portName)) { + objId = dmehostid; + break; + } + } + } + } + // 如果主机\不存在就创建并得到主机 + if (StringUtils.isEmpty(objId)) { + objIds.add(createHostOnDme(hostNameAndHostIdList.get(hostId), hostId)); + } else { + objIds.add(objId); + } + } + } catch (DmeException ex) { + LOG.error("checkOrCreateToHost error:", ex); + throw new DmeException(ex.getMessage()); + } + return objIds; + + } + + /** + * @return List + * @throws DmeException + * @Description: 创建主机组新方法 + * @Param clusterIdList + * @author yc + * @Date 2021/6/2 11:09 + */ + private List createHostGroupIdNew(List clusterIdList,String hostGroupVolumid) throws DmeException { + + ArrayList objIds = new ArrayList(); + String radomStr = new SimpleDateFormat("yyMMddHHmmssSSS").format(new Date(System.currentTimeMillis())).toString(); + // 取得集群下的所有主机 + for (String clusterObjectId : clusterIdList) { + String objId = ""; + String vmwarehosts = vcsdkUtils.getHostsOnCluster(clusterObjectId); + if (StringUtils.isEmpty(vmwarehosts)) { + throw new DmeException("the cluster has no host"); + } + + List> vmwarehostlists = gson.fromJson(vmwarehosts, + new TypeToken>>() { + }.getType()); + if (vmwarehostlists != null && vmwarehostlists.size() > 0) { + // 分别检查每一个主机是否存在,如果不存在就创建 + List hostlists = new ArrayList<>(); + Map>> allinitionators = getAllInitionator(); + //todo 需要从检查联通性的主机中把已经挂载的剔除 + //todo 20210621 修改挂载集群时映射主机组时需要剔除已经隐射的主机 + if (!StringUtils.isEmpty(hostGroupVolumid)) { + List mappedHostid = new ArrayList<>(); + if (!StringUtils.isEmpty(hostGroupVolumid)) { + List attachmentList = findMappedHostsAndClusters(hostGroupVolumid); + if (!CollectionUtils.isEmpty(attachmentList)) { + for (Attachment attach : attachmentList) { + if (!StringUtils.isEmpty(StringUtil.dealQuotationMarks(attach.getHostId()))) { + mappedHostid.add(StringUtil.dealQuotationMarks(attach.getHostId())); + } + } + } + } + //从集群中的主机中剔除已经映射的主机 + vmwarehostlists = deleteMappedHost(vmwarehostlists, mappedHostid,allinitionators); + } + for (Map hostmap : vmwarehostlists) { + String tmpHostId = checkOrCreateToHost(ToolUtils.getStr(hostmap.get(HOST_NAME)), + ToolUtils.getStr(hostmap.get(HOSTID)), allinitionators); + if (!StringUtils.isEmpty(tmpHostId)) { + hostlists.add(tmpHostId); + } + } + // 在DME中创建主机组 + //todo 从主机集合中剔除已经映射的主机 + if (!CollectionUtils.isEmpty(hostlists)) { + Map params = new HashMap<>(); + params.put("cluster", + vcsdkUtils.getVcConnectionHelper().objectId2Mor(clusterObjectId).getValue() + "-C" + radomStr); + params.put("hostids", hostlists); + Map hostmap = dmeAccessService.createHostGroup(params); + if (hostmap != null && hostmap.get(DmeConstants.ID) != null) { + objId = ToolUtils.getStr(hostmap.get(ID_FIELD)); + } + } + } + objIds.add(objId); + } + return objIds; + } + + /** + * @Description: 检查主机或者主机组的联通性 + * @author yc + * @Date 2021/5/12 15:49 + */ + private List estimateConnectivityOfHostOrHostgroupNew(String storageId, List objIds, String hostgroupId) throws DmeException { + Map requestBody = new HashMap<>(); + if (StringUtils.isEmpty(storageId)) { + LOG.error("estimate connectivity of host or hostgroup storageid param error!", storageId); + throw new DmeException("estimate connectivity of host or hostgroup , storageid param error!"); + } + requestBody.put("storage_id", storageId); + if (!CollectionUtils.isEmpty(objIds)) { + //检查主机连通性参数 + requestBody.put("host_ids", objIds); + } + if (!StringUtils.isEmpty(hostgroupId)) { + //检查主机组连通性参数 + requestBody.put("hostgroup_id", hostgroupId); + } + String url = DmeConstants.DME_ESTIMATE_CONNECTIVITY; + Map param = new HashMap<>(); + LOG.info("check connectivity of host or horstgroup on dme ! {" + gson.toJson(requestBody) + "}"); + ResponseEntity responseEntity = dmeAccessService.access(url, HttpMethod.POST, gson.toJson(requestBody)); + List resultMapList = new ArrayList<>(); + if (responseEntity.getStatusCodeValue() == HttpStatus.OK.value()) { + String body = responseEntity.getBody(); + JsonObject jsonObject = new JsonParser().parse(body).getAsJsonObject(); + JsonArray jsonArray = jsonObject.get("results").getAsJsonArray(); + for (JsonElement jsonElement : jsonArray) { + JsonObject element = jsonElement.getAsJsonObject(); + String id = ToolUtils.jsonToStr(element.get("host_id")); + String status = ToolUtils.jsonToStr(element.get("status")); + // 连通性异常主机结果统计 + if (status.equalsIgnoreCase("NOT_CONNECT")) { + resultMapList.add(id); + } + } + } else { + throw new DmeException("check connectivity of host or horstgroup on dme failed!"); + } + return resultMapList; + } + + /** + * @Description: 检查主机组是否存在,不存在就创建主机组 + * @author yc + * @Date 2021/5/12 16:17 + */ + private List getOrCreateHostGroupIdNew(List clusterIdList, String volumeId) throws DmeException { + + ArrayList objIds = new ArrayList(); + String subVolumeId = ToolUtils.handleString(volumeId); + // 取得集群下的所有主机 + for (String clusterObjectId : clusterIdList) { + String objId = ""; + String vmwarehosts = vcsdkUtils.getHostsOnCluster(clusterObjectId); + if (StringUtils.isEmpty(vmwarehosts)) { + new DmeException("the cluster has no host"); + } + + List> vmwarehostlists = gson.fromJson(vmwarehosts, + new TypeToken>>() { + }.getType()); + if (vmwarehostlists != null && vmwarehostlists.size() > 0) { + // 分别检查每一个主机是否存在,如果不存在就创建 + List hostlists = new ArrayList<>(); + Map>> allinitionators = getAllInitionator(); + for (Map hostmap : vmwarehostlists) { + String tmpHostId = checkOrCreateToHost(ToolUtils.getStr(hostmap.get(HOST_NAME)), + ToolUtils.getStr(hostmap.get(HOSTID)), allinitionators); + if (!StringUtils.isEmpty(tmpHostId)) { + hostlists.add(tmpHostId); + } + } + // 在DME中创建主机组 + if (!CollectionUtils.isEmpty(hostlists)) { + Map params = new HashMap<>(); + params.put("cluster", + vcsdkUtils.getVcConnectionHelper().objectId2Mor(clusterObjectId).getValue() + "-" + subVolumeId); + params.put("hostids", hostlists); + Map hostmap = dmeAccessService.createHostGroup(params); + if (hostmap != null && hostmap.get(DmeConstants.ID) != null) { + objId = ToolUtils.getStr(hostmap.get(ID_FIELD)); + } + } + } + objIds.add(objId); + } + return objIds; + } + + /** + * @return taskIds + * @Description: 将lun映射给主机和主机组并且检查映射状态 + * @Param volumeIds, hostIds, clusterIds + * @author yc + * @Date 2021/5/13 15:29 + */ + private Map> lunMappingToHostOrHostgroupNew(List volumeIds, List hostIds, List clusterIds) + throws DmeException { + Map params = new HashMap<>(); + Map> mappingResultMap = new HashMap<>(); + List mappedList = new ArrayList<>(); + List unMappedList = new ArrayList<>(); + ResponseEntity responseEntity = null; + String descriptionEn = null; + String descriptionCn = null; + + if (!CollectionUtils.isEmpty(clusterIds)) { + String url = DmeConstants.MOUNT_VOLUME_TO_HOSTGROUP_URL; + for (String clusterId : clusterIds) { + params.put(HOST_GROUP_ID1, clusterId); + params.put(VOLUME_IDS, volumeIds); + LOG.info("lun mapping to host or hostgroup request params:{}", gson.toJson(params)); + try { + responseEntity = dmeAccessService.access(url, HttpMethod.POST, gson.toJson(params)); + } catch (Exception e) { + unMappedList.add(clusterId); + } + if (!StringUtils.isEmpty(responseEntity) && responseEntity.getStatusCodeValue() == HttpStatus.ACCEPTED.value()) { + JsonObject object = new JsonParser().parse(responseEntity.getBody()).getAsJsonObject(); + String taskId = ToolUtils.jsonToStr(object.get("task_id")); + TaskDetailInfoNew result = taskService.queryTaskByIdReturnMainTask(taskId, longTaskTimeOut); + if (3 == result.getStatus() && 100 == result.getProgress()) { + mappedList.add(clusterId); + } else { + unMappedList.add(clusterId); + descriptionEn = result.getDetailEn(); + descriptionCn = result.getDetailCn(); + } + } else { + unMappedList.add(clusterId); + descriptionEn = "request lun mapping to hostgroup return error!"; + descriptionCn = "请求DME,将Lun映射给主机组,DME返回失败!"; + } + //将联通性检测失败的主机组也放至映射失败的集合中 + mappingResultMap.put("clusterMapped", mappedList); + mappingResultMap.put("clusterUnmapped", unMappedList); + } + } else if (!CollectionUtils.isEmpty(hostIds)) { + String url = DmeConstants.DME_HOST_MAPPING_URL; + for (String hostId : hostIds) { + params.put(HOST_ID, hostId); + params.put(VOLUME_IDS, volumeIds); + LOG.info("lun mapping to host or hostgroup request params:{}", gson.toJson(params)); + responseEntity = dmeAccessService.access(url, HttpMethod.POST, gson.toJson(params)); + if (!StringUtils.isEmpty(responseEntity) && responseEntity.getStatusCodeValue() == HttpStatus.ACCEPTED.value()) { + JsonObject object = new JsonParser().parse(responseEntity.getBody()).getAsJsonObject(); + String taskId = ToolUtils.jsonToStr(object.get("task_id")); + TaskDetailInfoNew result = taskService.queryTaskByIdReturnMainTask(taskId, longTaskTimeOut); + if (3 == result.getStatus() && 100 == result.getProgress()) { + mappedList.add(hostId); + } else { + unMappedList.add(hostId); + descriptionEn = result.getDetailEn(); + descriptionCn = result.getDetailCn(); + } + } else { + unMappedList.add(hostId); + descriptionEn = "request lun mapping to host return error!"; + descriptionCn = "请求DME,将Lun映射给主机,DME返回失败!"; + + } + //将联通性检测失败的主机也放至映射失败的集合中 + mappingResultMap.put("hostMapped", mappedList); + mappingResultMap.put("hostUnmapped", unMappedList); + } + } + if (!StringUtils.isEmpty(descriptionEn)) { + mappingResultMap.put("descriptionEN", Arrays.asList(descriptionEn)); + mappingResultMap.put("descriptionCN", Arrays.asList(descriptionCn)); + } + return mappingResultMap; + } + + /** + * @return @return + * @throws + * @Description: 回滚函数 + * @Param @param null + * @author yc + * @Date 2021/5/13 17:22 + */ + private void rollBackNew(String volumeId, List dmeHostIds, List demHostGroupIds, Boolean isCreated, Boolean isMapping) throws DmeException { + ResponseEntity responseEntity = null; + String taskId = ""; + if (!StringUtils.isEmpty(volumeId)) { + Map requestParam = new HashMap<>(); + //解除映射,删除已创建的卷 + requestParam.put(VOLUMEIDS, Arrays.asList(volumeId)); + if (isCreated && isMapping) { + if (!CollectionUtils.isEmpty(dmeHostIds) && isMapping) { + for (String dmeHostId : dmeHostIds) { + requestParam.put(HOST_ID, dmeHostId); + responseEntity = hostUnmapping(requestParam); + } + } + if (!CollectionUtils.isEmpty(demHostGroupIds) && isMapping) { + for (String demHostGroupId : demHostGroupIds) { + requestParam.put(HOST_GROUP_ID1, demHostGroupId); + responseEntity = hostGroupUnmapping(requestParam); + } + } + if (responseEntity.getStatusCodeValue() == HttpStatus.ACCEPTED.value()) { + taskId = ToolUtils.jsonToStr( + new JsonParser().parse(ToolUtils.getStr(responseEntity.getBody())).getAsJsonObject() + .get("task_id")); + } + } + Set taskIds = new HashSet<>(); + taskIds.add(taskId); + if (taskId.equals("") || taskService.checkTaskStatusLarge(taskIds, longTaskTimeOut)) { + volumeDelete(requestParam); + if (!CollectionUtils.isEmpty(demHostGroupIds)) { + for (String demHostGroupId : demHostGroupIds) { + deleteHostgroup(demHostGroupId); + } + } + } + } + } + + /** + * @return @return + * @throws + * @Description: vmfs挂载新方法,支持批量选择主机或者主机组 + * @Param @param null + * @author yc + * @Date 2021/5/14 10:41 + */ + @Override + public List> mountVmfsNew(Map params) throws DmeException { + //校验参数不能为空 + //todo 增加逻辑(如果存储设备是以主机创建,挂载时就只支持按主机挂载) + if (CollectionUtils.isEmpty(params)) { + throw new DmeException("mount vmfs error, params is null"); + } + //获取前端页面入参 + Object ss = params.get(CHOOSEDEVICE); + //校验前端选择的主机或者主机组不能为空 + if (StringUtils.isEmpty(params.get(CHOOSEDEVICE))) { + throw new DmeException("create vmfs the params is error"); + } + List> chooseDevicelists = gson.fromJson(gson.toJsonTree(ss), + new TypeToken>>() { + }.getType()); + + if (CollectionUtils.isEmpty(chooseDevicelists)) { + throw new DmeException("create vmfs the params is error"); + } + HashSet deviceTypeSet = getDeviceTypeSet2(chooseDevicelists); + //根据前端的存储获取存储的创建方式以及每个存储所对应的卷信息 + HashMap> dataStorageMap = new HashMap>(); + String dataStoreObjectId = null; + String hostVolumid = null; + String hostGroupVolumid = null; + + HashSet createTypeSet = new HashSet(); + if (params.get(DATASTORE_OBJECT_IDS) != null) { + List dataStoreObjectIds = (List) params.get(DATASTORE_OBJECT_IDS); + if (!CollectionUtils.isEmpty(dataStoreObjectIds) && dataStoreObjectIds.size() == 1) { + dataStoreObjectId = dataStoreObjectIds.get(0); + } else { + throw new DmeException("create vmfs the params is error"); + } + if (StringUtils.isEmpty(dataStoreObjectId)) { + throw new DmeException("create vmfs the params is error"); + } + getDataStorageInfo(dataStorageMap, dataStoreObjectId); + } + //对前端入参逻辑进行校验 + + String type = dataStorageMap.get(dataStoreObjectId).get(TYPE); + if (StringUtils.isEmpty(type)) { + throw new DmeException("get method creating vmfs error "); + } + createTypeSet.add(type); + if (HOST.equalsIgnoreCase(type)) { + hostVolumid = dataStorageMap.get(dataStoreObjectId).get("volumeId"); + } else { + hostGroupVolumid = dataStorageMap.get(dataStoreObjectId).get("volumeId"); + } + Map hostIdToIp = getHostNameAndHostIdList(chooseDevicelists); + List hostIds = new ArrayList<>(hostIdToIp.keySet()); + List clusterIds = getClusterIdList(chooseDevicelists); + //1.前端入参的选择的挂载方式为主机 + if (deviceTypeSet.size() == 1 && deviceTypeSet.contains(HOST)) { + //1.1如果存储的创建方式为主机,检查主机连通性,将原有的lun映射给新的主机 + if (!StringUtils.isEmpty(hostVolumid)) { + Map>> allinitionators = getAllInitionator(); + Map paraMap = new HashMap<>(); + paraMap.put(STORAGE_ID, dataStorageMap.get(dataStoreObjectId).get("storageId")); + Map> hostStatusMap1 = checkHostNewNoCheckCluster(paraMap, allinitionators, chooseDevicelists); + List objHostIds = hostStatusMap1.get("nomalHost"); + List unmappingAndNomalHostids = getUnmappingAndNomalHost(hostVolumid, objHostIds); + Map> mappingResult1 = lunMappingToHostOrHostgroupNew(Arrays.asList(hostVolumid), unmappingAndNomalHostids, null); + List mappedHostid = mappingResult1.get("hostMapped"); + if (!CollectionUtils.isEmpty(objHostIds) && CollectionUtils.isEmpty(unmappingAndNomalHostids)) { + mappedHostid = objHostIds; + } + if (!CollectionUtils.isEmpty(mappedHostid)) { + try { + for (String hostId : hostIds) { + Map dsmap = new HashMap<>(); + dsmap.put(NAME_FIELD, dataStorageMap.get(dataStoreObjectId).get("dataStoreName")); + vcsdkUtils.mountVmfsOnClusterNew(gson.toJson(dsmap), null, hostId); + } + } catch (Exception e) { + //如果抛出异常,需要解除映射 + HashMap requestParam = new HashMap<>(); + requestParam.put(VOLUMEIDS, Arrays.asList(hostVolumid)); + for (String dmeHostId : mappedHostid) { + requestParam.put(HOST_ID, dmeHostId); + ResponseEntity responseEntity = hostUnmapping(requestParam); + LOG.info("mountVmfsNew rollback:" + responseEntity); + } + } + } + //1.2如果存储的创建方式为集群,需要判断前端入参的主机是否包含在已经映射的集群中,包含的话,将主机加入主机组,继续挂载;不包含,将主机以单主机的方式映射 + } else if (!StringUtils.isEmpty(hostGroupVolumid)) { + + if (!CollectionUtils.isEmpty(hostIds)) { + //根据非独立出来的主机重新组装对象 + List> chooseDeviceNew = buildChooseDevice(chooseDevicelists, hostIds); + Map>> allinitionators = getAllInitionator(); + Map paraMap = new HashMap<>(); + paraMap.put(STORAGE_ID, dataStorageMap.get(dataStoreObjectId).get("storageId")); + Map> hostStatusMap1 = checkHostNewNoCheckCluster(paraMap, allinitionators, chooseDeviceNew); + List objHostIds = hostStatusMap1.get("nomalHost"); + //增加查询lun对应的已经映射的主机,映射之前从连通性正常的主机组中移除已经映射的主机 + List unmappingAndNomalHostids = getUnmappingAndNomalHost(hostGroupVolumid, objHostIds); + Map> mappingResult1 = lunMappingToHostOrHostgroupNew(Arrays.asList(hostGroupVolumid), unmappingAndNomalHostids, null); + List mapingHostid = mappingResult1.get("hostMapped"); + if (!CollectionUtils.isEmpty(objHostIds) && CollectionUtils.isEmpty(unmappingAndNomalHostids)) { + mapingHostid = objHostIds; + } + if (!CollectionUtils.isEmpty(mapingHostid)) { + try { + for (String hostId : hostIds) { + Map dsmap = new HashMap<>(); + dsmap.put(NAME_FIELD, dataStorageMap.get(dataStoreObjectId).get("dataStoreName")); + vcsdkUtils.mountVmfsOnClusterNew(gson.toJson(dsmap), null, hostId); + } + } catch (Exception e) { + //如果抛出异常,需要解除映射 + HashMap requestParam = new HashMap<>(); + requestParam.put(VOLUMEIDS, Arrays.asList(hostGroupVolumid)); + for (String dmeHostId : mapingHostid) { + requestParam.put(HOST_ID, dmeHostId); + ResponseEntity responseEntity = hostUnmapping(requestParam); + LOG.info("mountVmfsNew rollback:" + responseEntity); + } + } + } + + } + } + } + //2.前端入参的选择的挂载方式为集群 + if (deviceTypeSet.size() == 1 && deviceTypeSet.contains(CLUSTER)) { + //2.1如果存储的创建方式为主机,直接抛出异常 + if (!StringUtils.isEmpty(hostVolumid)) { + throw new DmeException("vmfs was created with host not allow to mount the cluster"); + } + //2.2如果存储的创建方式为集群,将lun隐射为新的主机组,然后将存储挂载在集群上; + if (!CollectionUtils.isEmpty(clusterIds) && !StringUtils.isEmpty(hostGroupVolumid)) { + //2.2.1检查集群的联通性 + HashMap param = new HashMap(); + param.put(STORAGE_ID, dataStorageMap.get(dataStoreObjectId).get("storageId")); + List>> maps = checkOrCreateToHostGroupNew2(param, chooseDevicelists, hostGroupVolumid); + List hostGroupIds = new ArrayList<>(); + for (Map> map : maps) { + if (!CollectionUtils.isEmpty(map.get("nomalCluster"))) { + hostGroupIds.addAll(map.get("nomalCluster")); + } + } + //maps.stream().forEach(map -> hostGroupIds.addAll(map.get("nomalCluster"))); + if (!CollectionUtils.isEmpty(hostGroupIds)) { + //将lun映射给主机组,然后挂载集群 + for (String hostGroupId : hostGroupIds) { + String taskid = lunMappingToHostOrHostgroup(Arrays.asList(hostGroupVolumid), null, hostGroupId); + TasksResultObject result = taskService.checkTaskStatusNew(taskid, 0); + + } + Map dsmap = new HashMap<>(); + dsmap.put(NAME_FIELD, dataStorageMap.get(dataStoreObjectId).get("dataStoreName")); + for (String cluster : clusterIds) { + vcsdkUtils.mountVmfsOnClusterNew(gson.toJson(dsmap), cluster, null); + } + } else { + throw new DmeException("check connectivity of cluster error"); + } + } + } + //3.前端入参的选择方式为集群加主机,此时只支持以集群方式创建的数据存储。 + if (deviceTypeSet.size() > 1) { + if (!StringUtils.isEmpty(hostVolumid)) { + throw new DmeException("vmfs was created with host not allow to mount the cluster"); + } + //3.1处理主机集合 + if (!CollectionUtils.isEmpty(hostIds)) { + //根据非独立出来的主机重新组装对象 + List> chooseDeviceNew = buildChooseDevice(chooseDevicelists, hostIds); + Map>> allinitionators = getAllInitionator(); + Map paraMap = new HashMap<>(); + paraMap.put(STORAGE_ID, dataStorageMap.get(dataStoreObjectId).get("storageId")); + Map> hostStatusMap1 = checkHostNewNoCheckCluster(paraMap, allinitionators, chooseDeviceNew); + List objHostIds = hostStatusMap1.get("nomalHost"); + //增加查询lun对应的已经映射的主机,映射之前从连通性正常的主机组中移除已经映射的主机 + List unmappingAndNomalHostids = getUnmappingAndNomalHost(hostGroupVolumid, objHostIds); + Map> mappingResult1 = lunMappingToHostOrHostgroupNew(Arrays.asList(hostGroupVolumid), unmappingAndNomalHostids, null); + List mapingHostid = mappingResult1.get("hostMapped"); + if (!CollectionUtils.isEmpty(objHostIds) && CollectionUtils.isEmpty(unmappingAndNomalHostids)) { + mapingHostid = objHostIds; + } + if (!CollectionUtils.isEmpty(mapingHostid)) { + try { + for (String hostId : hostIds) { + Map dsmap = new HashMap<>(); + dsmap.put(NAME_FIELD, dataStorageMap.get(dataStoreObjectId).get("dataStoreName")); + vcsdkUtils.mountVmfsOnClusterNew(gson.toJson(dsmap), null, hostId); + } + } catch (Exception e) { + //如果抛出异常,需要解除映射 + HashMap requestParam = new HashMap<>(); + requestParam.put(VOLUMEIDS, Arrays.asList(hostGroupVolumid)); + for (String dmeHostId : mapingHostid) { + requestParam.put(HOST_ID, dmeHostId); + ResponseEntity responseEntity = hostUnmapping(requestParam); + LOG.info("mountVmfsNew rollback:" + responseEntity); + } + } + } + } + //3.2处理集群集合 + if (!CollectionUtils.isEmpty(clusterIds) && !StringUtils.isEmpty(hostGroupVolumid)) { + //2.2.1检查集群的联通性 + HashMap param = new HashMap(); + param.put(STORAGE_ID, dataStorageMap.get(dataStoreObjectId).get("storageId")); + List>> maps = checkOrCreateToHostGroupNew2(param, chooseDevicelists, hostGroupVolumid); + List hostGroupIds = new ArrayList<>(); + for (Map> map : maps) { + if (!CollectionUtils.isEmpty(map.get("nomalCluster"))) { + hostGroupIds.addAll(map.get("nomalCluster")); + } + } + //maps.stream().forEach(map -> hostGroupIds.addAll(map.get("nomalCluster"))); + if (!CollectionUtils.isEmpty(hostGroupIds)) { + //将lun映射给主机组,然后挂载集群 + for (String hostGroupId : hostGroupIds) { + String taskid = lunMappingToHostOrHostgroup(Arrays.asList(hostGroupVolumid), null, hostGroupId); + TasksResultObject result = taskService.checkTaskStatusNew(taskid, 0); + + } + Map dsmap = new HashMap<>(); + dsmap.put(NAME_FIELD, dataStorageMap.get(dataStoreObjectId).get("dataStoreName")); + for (String cluster : clusterIds) { + vcsdkUtils.mountVmfsOnClusterNew(gson.toJson(dsmap), cluster, null); + } + } else { + throw new DmeException("check connectivity of cluster error"); + } + } + } + return null; + } + + + private List getUnmappingAndNomalHost(String hostGroupVolumid, List objHostIds) throws DmeException { + //首选根据卷id查询卷已经隐射的主机id + List attachmentList = findMappedHostsAndClusters(hostGroupVolumid); + List mappedHostid = new ArrayList<>(); + if (!CollectionUtils.isEmpty(attachmentList)){ + for (Attachment attach : attachmentList) { + if (!StringUtils.isEmpty(StringUtil.dealQuotationMarks(attach.getHostId()))) { + mappedHostid.add(StringUtil.dealQuotationMarks(attach.getHostId())); + } + } + } + List unMappedAndNomalHostIds = new ArrayList<>(); + if (!CollectionUtils.isEmpty(mappedHostid) && !CollectionUtils.isEmpty(objHostIds)){ + //将已经映射的主机id从主机中剔除 + for (String hostId : objHostIds) { + if (!mappedHostid.contains(hostId)){ + unMappedAndNomalHostIds.add(hostId); + } + } + }else { + unMappedAndNomalHostIds = objHostIds; + } + return unMappedAndNomalHostIds; + } + + /* private List getDmeHostIdByHostId(List dependentHosts, Map hostIdToIp) throws DmeException { + + List dmeHostId = new ArrayList<>(); + if (!CollectionUtils.isEmpty(dependentHosts)) { + + for (String hostid : dependentHosts) { + if (!CollectionUtils.isEmpty(hostIdToIp) && !StringUtils.isEmpty(hostIdToIp.get(hostid))) { + List> hostResult = dmeAccessService.getDmeHosts2(hostIdToIp.get(hostid)); + if (StringUtils.isEmpty(hostResult) || CollectionUtils.isEmpty(hostResult)) { + throw new DmeException("get hostid from dme return empty"); + } + String hostDmeId = ToolUtils.getStr(hostResult.get(0).get(ID_FIELD)); + if (!StringUtils.isEmpty(hostDmeId)) { + dmeHostId.add(hostid); + } + } + } + } + return dmeHostId; + }*/ + + private List getIndependentHosts(List hostIds, List nonIndependentHosts) { + List independentHosts = new ArrayList<>(); + for (String hostid : hostIds) { + if (!nonIndependentHosts.contains(hostid)) { + independentHosts.add(hostid); + } + } + return independentHosts; + } + + + private List getValues(List> clusterTempList) { + List values = new ArrayList<>(); + if (!CollectionUtils.isEmpty(clusterTempList)){ + for (Map map:clusterTempList) { + if (!StringUtils.isEmpty(map.get(CLUSTER_ID))); + values.add(map.get(CLUSTER_ID)); + } + } + return values; + } + + private List> buildChooseDevice(List> chooseDevicelists, List independentHosts) { + List> chooseDeviceNewlists = new ArrayList<>(); + if (!CollectionUtils.isEmpty(chooseDevicelists) && !CollectionUtils.isEmpty(independentHosts)) { + for (String hostid : independentHosts) { + Map chooseMap = new HashMap<>(); + for (Map choose : chooseDevicelists) { + if (hostid.equalsIgnoreCase(choose.get("clusterId"))) { + chooseMap.put("deviceId", hostid); + chooseMap.put("deviceName", choose.get("clusterName")); + chooseMap.put("deviceType", "host"); + } + } + chooseDeviceNewlists.add(chooseMap); + } + + } + return chooseDeviceNewlists; + } + + /** + * @Description: 获取指定lun最近映射的主机组id + * @Param clusterVolumIds + * @return hostgroupids + * @throws DmeException + * @author yc + * @Date 2021/6/4 9:47 + */ + private String getLasterMappingHostGroup(String clusterVolumId) throws DmeException { + //首先校验入参的集合 + String hostgroupid = null; + if (!StringUtils.isEmpty(clusterVolumId)){ + //查询指定lun获取最近时间的主机组id + List attachmentList = findMappedHostsAndClusters(clusterVolumId); + Attachment maxdatares = attachmentList.stream().filter(attachment -> !StringUtils.isEmpty(attachment.getAttachedHostGroup())).max(Comparator.comparing(attachment1 -> attachment1.getAttachedAtDate())).get(); + if (!StringUtils.isEmpty(maxdatares) && !StringUtils.isEmpty(maxdatares.getAttachedHostGroup())){ + hostgroupid = maxdatares.getAttachedHostGroup(); + } + } + if(StringUtils.isEmpty(hostgroupid)){ + throw new DmeException("get hostgroupid error"); + } + return hostgroupid; + } + /** + * @Description: 根据存储设备获取卷的信息 + * @Param dataStorageMap,dataStoreObjectIds + * @throws DmeException + * @author yc + * @Date 2021/6/3 10:54 + */ + private void getDataStorageInfo (HashMap> dataStorageMap, String dataStoreObjectId) throws DmeException { + HashMap dataInfo = new HashMap(); + DmeVmwareRelation dvr = dmeVmwareRalationDao.getDmeVmwareRelationByDsId(dataStoreObjectId); + if (!StringUtils.isEmpty(dvr)) { + String volumeId = dvr.getVolumeId(); + String dataStoreName = dvr.getStoreName(); + String storageId = dvr.getStorageDeviceId(); + if (StringUtils.isEmpty(volumeId)){ + throw new DmeException("get volumeid fail"); + } + dataInfo.put("volumeId", volumeId); + dataInfo.put("dataStoreName", dataStoreName); + dataInfo.put("storageId", storageId); + + List attachmentList = findMappedHostsAndClusters(volumeId); + //获取映射数据中时间最早的映射方式 + if (CollectionUtils.isEmpty(attachmentList)){ + throw new DmeException("query lun info error"); + } + Attachment mindatares = attachmentList.stream().min(Comparator.comparing(attachment -> attachment.getAttachedAtDate())).get(); + //判断时间最小的映射方式(如果为主机组,就返回‘cluster’,如果为主机返回‘host’,其他报错) + if (!StringUtils.isEmpty(mindatares.getAttachedHostGroup()) && !mindatares.getAttachedHostGroup().equalsIgnoreCase("null")) { + dataInfo.put(TYPE, CLUSTER); + }else if (!StringUtils.isEmpty(mindatares.getHostId()) && !mindatares.getHostId().equalsIgnoreCase("null")){ + dataInfo.put(TYPE, HOST); + }else { + throw new DmeException("get vmfs create method error ,the dataStoreObjectId = "+dataStoreObjectId); + } + } + dataStorageMap.put(dataStoreObjectId,dataInfo); + } + /** + * @Description: 获取各个主机和其对应主机组的映射关系 + * @Param hostIds + * @return List + * @throws VcenterException + * @author yc + * @Date 2021/5/20 16:26 + */ + private Map gethostToclusterMap(List hostIds) throws VcenterException { + //首先判断入参 + Map hostToclusterMap = new HashMap<>(); + if (CollectionUtils.isEmpty(hostIds)) + return hostToclusterMap; + List clusteridList = vcsdkUtils.getAllClusterIds(); + //循环主机id,判断主机所属的主机组 + for (String hostid : hostIds) { + for (String clusterid : clusteridList) { + List hosts = vcsdkUtils.getHostidsOnCluster(clusterid); + if (!CollectionUtils.isEmpty(hosts) && hosts.contains(hostid)) { + hostToclusterMap.put(hostid,clusterid); + } + } + } + return hostToclusterMap; + } + /** + * @Description: 将vfms挂载至虚拟机的新方法 + * @Param params,chooseDevicelists + * @throws VcenterException + * @author yc + * @Date 2021/5/14 15:24 + */ + private void mountVmfsOnVmwareNew(Map params, List> chooseDevicelists) throws VcenterException { + + //根据入参将主机和主机组区分开,分别调用vCenter在主机上扫描卷和Datastore + for (Map map : chooseDevicelists) { + if ("host".equalsIgnoreCase(map.get("deviceType"))) { + vcsdkUtils.scanDataStore(null, ToolUtils.getStr(map.get("deviceId"))); + } + if ("cluster".equalsIgnoreCase(map.get("deviceType"))) { + vcsdkUtils.scanDataStore(ToolUtils.getStr(map.get("deviceId")), null); + } + } + // 如果是需要扫描LUN来挂载,则需要执行下面的方法,dataStoreNames + if (params.get(DmeConstants.DATASTORENAMES) != null) { + List dataStoreNames = (List) params.get(DATASTORE_NAMES); + if (dataStoreNames != null && dataStoreNames.size() > 0) { + for (String dataStoreName : dataStoreNames) { + Map dsmap = new HashMap<>(); + dsmap.put(NAME_FIELD, dataStoreName); + for (Map map : chooseDevicelists) { + if ("host".equalsIgnoreCase(map.get("deviceType"))) { + vcsdkUtils.scanDataStore(null, ToolUtils.getStr(map.get("deviceId"))); + vcsdkUtils.mountVmfsOnCluster(gson.toJson(dsmap), null, + ToolUtils.getStr(map.get("deviceId"))); + } + if ("cluster".equalsIgnoreCase(map.get("deviceType"))) { + vcsdkUtils.mountVmfsOnCluster(gson.toJson(dsmap), ToolUtils.getStr(map.get("deviceId")), + null); + } + } + + } + } + } + } + + /** + * @Description: 根据storageid查询已经挂载的主机组信息并以树的结果返回 + * @Param storageId + * @return List + * @throws DmeException + * @author yc + * @Date 2021/5/14 15:40 + */ + @Override + public List getMountedHostGroupsAndHostReturnTree(String dataStoreObjectId) throws Exception { + + List clusterTreeList = new ArrayList<>(); + List> clusterList = new ArrayList<>(); + //首先根据存储id获取存储下已经挂载的主机信息 + List hostObjectIds= vcsdkUtils.getAllMountedHostId(dataStoreObjectId); + //判断主机是否属于集群,如果主机属于集群需要获取集群的信息,将主机添加至集群中 + try { + String clusterListStr = vcsdkUtils.getAllClusters(); + if (!StringUtils.isEmpty(clusterListStr)) { + clusterList = gson.fromJson(clusterListStr, new TypeToken>>() { + }.getType()); + } + } catch (Exception e) { + LOG.error("get all mounted hosts and clusters by datastoreobjectid error:", e); + throw new DmeException("get all mounted hosts and clusters by datastoreobjectid error:" + e.getMessage()); + } + Map> temp = new HashMap<>(); + HashSet hostIdSet = new HashSet<>(hostObjectIds); + if (!CollectionUtils.isEmpty(hostObjectIds) && !CollectionUtils.isEmpty(clusterList)) { + for (Map clusterMap : clusterList) { + List hosts = vcsdkUtils.getHostidsOnCluster(clusterMap.get(CLUSTER_ID)); + List hostMapTemp = new ArrayList<>(); + for (String hostid : hostObjectIds) { + if (!CollectionUtils.isEmpty(hosts) && hosts.contains(hostid)){ + hostMapTemp.add(hostid); + temp.put(clusterMap.get(CLUSTER_ID),hostMapTemp); + hostIdSet.remove(hostid); + } + } + } + } + //组装树数据 + if (!CollectionUtils.isEmpty(hostIdSet)){ + for (String hostId : hostIdSet) { + ClusterTree hostTree = new ClusterTree(); + hostTree.setClusterId(hostId); + hostTree.setClusterName(vcsdkUtils.getHostName(hostId)); + if (!StringUtils.isEmpty(hostTree.getClusterId())){ + clusterTreeList.add(hostTree); + } + } + } + if (!CollectionUtils.isEmpty(temp)){ + for (String clusterId: temp.keySet()) { + if (!CollectionUtils.isEmpty(temp.get(clusterId))){ + List childTemp = new ArrayList<>(); + for (String hostId : temp.get(clusterId)) { + ClusterTree hostTree = new ClusterTree(); + hostTree.setClusterId(hostId); + hostTree.setClusterName(vcsdkUtils.getHostName(hostId)); + childTemp.add(hostTree); + } + ClusterTree clusterTree = new ClusterTree(); + clusterTree.setClusterId(clusterId); + clusterTree.setClusterName(vcsdkUtils.getClusterNameByClusterId(clusterId)); + clusterTree.setChildren(childTemp); + clusterTreeList.add(clusterTree); + } + } + } + + + + return clusterTreeList; + } + + /** + * @throws DmeException + * @Description: 卸载vmfs新接口 + * @Param params + * @author yc + * @Date 2021/5/14 17:57 + */ + /** + @Override + public void unmountVmfsNew(Map params) throws DmeException { + //参数非空校验 + if (CollectionUtils.isEmpty(params)) { + throw new DmeException("unmount volume params is null!"); + } + //解析前端入参 + Object ss = params.get("chooseDevice"); + //校验前端选择的主机或者主机组不能为空 + if (StringUtils.isEmpty(params.get("chooseDevice"))) { + throw new DmeException("create vmfs the params is error"); + } + List> chooseDevicelists = gson.fromJson(gson.toJsonTree(ss), + new TypeToken>>() { + }.getType()); + if (CollectionUtils.isEmpty(chooseDevicelists)) { + throw new DmeException("create vmfs the params is error"); + } + //将前端参数按主机组和主机信息进行区分 + List hostIds = new ArrayList<>(); + List clusterIds = new ArrayList<>(); + for (Map chooseMap : chooseDevicelists) { + if ("host".equalsIgnoreCase(chooseMap.get("deviceType"))) { + if (!StringUtils.isEmpty(chooseMap.get("deviceId"))) { + hostIds.add(chooseMap.get("deviceId")); + } + } + if ("cluster".equalsIgnoreCase(chooseMap.get("deviceType"))) { + if (!StringUtils.isEmpty(chooseMap.get("deviceId"))) { + clusterIds.add(chooseMap.get("deviceId")); + } + } + } + //获取vmfs对应的存储数据信息 + List dataStoreObjectIds = new ArrayList<>(); + String volumeId = null; + String dataStoreName = null; + //List volumeIds = new ArrayList<>(); + if (!StringUtils.isEmpty(params.get(DATASTORE_OBJECT_IDS))) { + dataStoreObjectIds = (List) params.get(DATASTORE_OBJECT_IDS); + if (CollectionUtils.isEmpty(dataStoreObjectIds)) { + throw new DmeException("unmount volume params dataStoreObjectIds is null!"); + } + // List dataStoreNames = new ArrayList<>(); + for (String dsObjectId : dataStoreObjectIds) { + boolean isFoundVm = vcsdkUtils.hasVmOnDatastore(dsObjectId); + if (isFoundVm) { + LOG.info("vmfs unmount,the vmfs:{} contain vm,can not unmount!!!", dsObjectId); + continue; + } + DmeVmwareRelation dvr = dmeVmwareRalationDao.getDmeVmwareRelationByDsId(dsObjectId); + if (dvr == null) { + scanVmfs(); + dvr = dmeVmwareRalationDao.getDmeVmwareRelationByDsId(dsObjectId); + } + if (dvr != null) { + volumeId = dvr.getVolumeId(); + dataStoreName = dvr.getStoreName(); + } + } + //找到对应的lun数据信息 + if (!StringUtils.isEmpty(volumeId)) { + params.put(VOLUMEIDS, volumeId); + params.put(DATASTORE_NAMES, dataStoreName); + } + } + List taskIds = new ArrayList<>(); + boolean isUnmounted = false; + // if (!CollectionUtils.isEmpty(volumeIds)) { + if (!CollectionUtils.isEmpty(hostIds) && !StringUtils.isEmpty(volumeId)) { + for (String hostObjId : hostIds) { + Map hostMap = getDmeHostByHostObjeId2(hostObjId); + if (hostMap != null && hostMap.size() > 0) { + params.put(HOST_ID, ToolUtils.getStr(hostMap.get(ID_FIELD))); + //根据volumeid查询指定lun获取该lun映射的主机和主机组信息 + //如果该lun映射给的主机包含卸载主机,先解除lun和主机的映射关系,如果该lun只包含一个主机先接触隐射,然后删除lun,如果lun映射的主机不包含需要卸载的主机,返回成功, + List attachmentList= findMappedHostsAndClusters(volumeId); + //获取 + isUnmounted = findMappingVolumeToHostgroup(volumeIds, hostMap); + if (!isUnmounted) { + String taskId = unmountHostGetTaskId2(params); + if (!StringUtils.isEmpty(taskId)) { + taskIds.add(taskId); + } + } + } + } + } + if (!CollectionUtils.isEmpty(clusterIds)) { + for (String clusterObjId : clusterIds) { + // 根据cluster获取dme侧目标主机组 + Map hostGroupMappingOrientedVolume = + getHostGroupMappingOrientedVolume(clusterObjId, volumeIds); + if (!CollectionUtils.isEmpty(hostGroupMappingOrientedVolume)) { + List volumeids = new ArrayList<>(); + for (Map.Entry entry : hostGroupMappingOrientedVolume.entrySet()) { + volumeids.add(entry.getValue()); + params.put(HOST_GROUP_ID1, entry.getKey()); + params.put(VOLUME_IDS, volumeids); + String taskId = unmountHostGroupGetTaskId(params); + if (!StringUtils.isEmpty(taskId)) { + taskIds.add(taskId); + } + boolean isUnmappingHostgroup = taskService.checkTaskStatus(taskIds); + if (isUnmappingHostgroup) { + taskId = removeHostgroupGetTaskId(params); + } + if (!StringUtils.isEmpty(taskId)) { + taskIds.add(taskId); + } + } + } + } + } + + + + // 获取卸载的任务完成后的状态,默认超时时间10分钟 + if (taskIds.size() > 0) { + isUnmounted = taskService.checkTaskStatus(taskIds); + } + //根据前端入参的主机和主机组集合,首先判断如果主机正好构成主机组信息,直接删除主机组信息,如果是主机组的部分主机,直接删除主机信息 + //判断是否卸载vmfs上的全部主机或集群 若是 则删除dme侧的卷,目前卸载参数中的主机/集群只支持单个,所以vmfs只挂载了一个主机或集群dme侧就直接删除卷 + boolean isDeleteHostFalg = false; + boolean isDeleteClusterFalg = false; + if (!CollectionUtils.isEmpty(hostIds)) { + for (String dsObj : dataStoreObjectIds) { + List> hosts = getHostsByStorageId2(dsObj); + if (hosts != null && hosts.size() == 0) { + isDeleteHostFalg = true; + break; + } + } + } + if (!CollectionUtils.isEmpty(clusterIds)) { + for (String dsObjId : dataStoreObjectIds) { + List> hostGroups = getHostGroupsByStorageId2(dsObjId); + if (hostGroups != null && hostGroups.size() == 0) { + isDeleteClusterFalg = true; + break; + } + } + } + if (!isUnmounted) { + throw new DmeException( + "unmount volume precondition unmount host and hostGroup error(task status),taskIds:(" + gson.toJson( + taskIds) + ")!"); + } else { + // 如果是需要扫描LUN来卸载,则需要执行下面的方法,dataStoreNames + if (params.get(DmeConstants.DATASTORENAMES) != null) { + List dataStoreNames = (List) params.get(DATASTORE_NAMES); + if (dataStoreNames != null && dataStoreNames.size() > 0) { + for (String dataStoreName : dataStoreNames) { + Map dsmap = new HashMap<>(); + dsmap.put(NAME_FIELD, dataStoreName); + vcsdkUtils.unmountVmfsOnHostOrClusterNew(gson.toJson(dsmap), clusterIds, hostIds); + } + } + } + } + // 若卸载vmfs上的全部主机或集群 最后重新扫描 此步会自动删除vmfs + if (isDeleteHostFalg && isDeleteClusterFalg) { + vcsdkUtils.scanDataStoreNew(clusterIds, hostIds); + } + }*/ + /** + * @Description: 创建vmfs新方法-支持多主机或集群 + * @Param params, volumelist + * @throws DmeException + * @author yc + * @Date 2021/5/20 14:13 + */ + private void createOnVmwareNew(Map params, Map volumemap) throws DmeException { + VCenterInfo vcenterinfo = null; + if (!StringUtils.isEmpty(params.get(DmeConstants.SERVICELEVELID))) { + vcenterinfo = vcenterinfoservice.getVcenterInfo(); + } + final VCenterInfo vcentertemp = vcenterinfo; + //创建前先扫描hba,避免每次循环扫描 + Object ss = params.get("chooseDevice"); + + List> chooseDevicelists = gson.fromJson(gson.toJsonTree(ss), + new TypeToken>>() { + }.getType()); + Map hostObjectIdMap = getHostNameAndHostIdList(chooseDevicelists); + Set hostObjectIds = hostObjectIdMap.keySet(); + List clusterObjectIds = getClusterIdList(chooseDevicelists); + if (!CollectionUtils.isEmpty(hostObjectIds)) { + for (String hostObjectId : hostObjectIds) { + vcsdkUtils.rescanHbaByHostObjectId(hostObjectId); + } + } + if (!CollectionUtils.isEmpty(clusterObjectIds)) { + for (String clusterObjectId : clusterObjectIds) { + vcsdkUtils.rescanHbaByClusterObjectId(clusterObjectId); + } + } + Map paramstemp = new HashMap<>(params); + try { + // 创建vmware中的vmfs存储。 + paramstemp.put(VOLUME_WWN, volumemap.get(VOLUME_WWN)); + paramstemp.put(VOLUME_NAME, volumemap.get(VOLUME_NAME)); + String dataStoreStr = createVmfsOnVmwareNew(paramstemp, hostObjectIdMap, clusterObjectIds); + if (!StringUtils.isEmpty(dataStoreStr)) { + Map dataStoreMap = gson.fromJson(dataStoreStr, + new TypeToken>() { + }.getType()); + if (dataStoreMap != null) { + // 将DME卷与vmfs的关系保存数据库,因为可以同时创建几个卷,无法在此得到对应关系,所以此处不再保存关系信息 + saveDmeVmwareRalation(volumemap, dataStoreMap); + // 关联服务等级 + if (!StringUtils.isEmpty(paramstemp.get(SERVICE_LEVEL_ID))) { + String serviceLevelName = ToolUtils.getStr(paramstemp.get(SERVICE_LEVEL_NAME)); + vcsdkUtils.attachTag(ToolUtils.getStr(dataStoreMap.get("type")), + ToolUtils.getStr(dataStoreMap.get(ID_FIELD)), serviceLevelName, vcentertemp); + } + } + List volumeIds = new ArrayList<>(); + String volumeId = ToolUtils.getStr(volumemap.get(VOLUME_ID)); + volumeIds.add(volumeId); + //将vmfs挂载到其他主机上 + if (hostObjectIds.size() > 1){ + //ArrayList hostObjectIdList = new ArrayList<>(hostObjectIds); + //List hostObjectIdListnew = Arrays.asList(hostObjectIdList.remove(0)); + /*for (String objhostid : hostObjectIdListnew) { + Map tempparams = new HashMap<>(); + tempparams.put(VOLUMEIDS,volumeIds);*/ + mountVmfsOnVmwareNew(params, chooseDevicelists); + + //taskids.add( mountVmfsToHost(tempparams, objhostid) ); + // } + } + } else { + throw new DmeException("vmware create vmfs error:" + params.get(VOLUME_NAME)); + } + } catch (Exception e) { + LOG.info("vmware create vmfs error:" + params.get(VOLUME_NAME)); + } + } + /** + * @Description: 在虚拟机上创建vmfs新方法 + * @Param params,hostObjectIdMap,clusterObjectIds + * @return String + * @throws DmeException + * @author yc + * @Date 2021/5/20 14:10 + */ + private String createVmfsOnVmwareNew(Map params, Map hostObjectIdMap, + List clusterObjectIds) throws DmeException { + String dataStoreStr = ""; + LOG.info("create vmfs on vmware begin !"); + try { + if (params != null) { + // 创建vmware中的vmfs存储。 cluster host + List hostObjectIds = new ArrayList<>(hostObjectIdMap.keySet()); + String datastoreName = ToolUtils.getStr(params.get(NAME_FIELD)); + int capacity = ToolUtils.getInt(params.get(CAPACITY)); + String existVolumeWwn = ToolUtils.getStr(params.get(VOLUME_WWN)); + String existVolumeName = ToolUtils.getStr(params.get(VOLUME_NAME)); + String volumeName = ToolUtils.getStr(params.get(VOLUMENAME)); + existVolumeName = existVolumeName.replaceAll(volumeName, ""); + + // 根据后缀序号改变VMFS的名称 + datastoreName = datastoreName + existVolumeName; + + // 从主机或集群中找出最接近capacity的LUN + Map hsdmap = new HashMap<>(); + ArrayList> hsdmapList = new ArrayList>(); + if (!CollectionUtils.isEmpty(hostObjectIds)) { + hsdmap = vcsdkUtils.getLunsOnHost(hostObjectIds.get(0), capacity, existVolumeWwn); + } + if (!CollectionUtils.isEmpty(clusterObjectIds)) { + hsdmap = vcsdkUtils.getLunsOnCluster(clusterObjectIds.get(0), capacity, existVolumeWwn); + } + + int vmfsMajorVersion = ToolUtils.getInt(params.get("version")); + int unmapGranularity = ToolUtils.getInt(params.get("spaceReclamationGranularity")); + int blockSize = ToolUtils.getInt(params.get("blockSize")); + String unmapPriority = ToolUtils.getStr(params.get("spaceReclamationPriority")); + dataStoreStr = vcsdkUtils.createVmfsDataStore(hsdmap, capacity, datastoreName, vmfsMajorVersion, + blockSize, unmapGranularity, unmapPriority); + + // 如果创建成功,扫描集群中的其他主机 + if (!CollectionUtils.isEmpty(clusterObjectIds)) { + vcsdkUtils.scanDataStore(clusterObjectIds.get(0), null); + } + } + } catch (DmeException e) { + LOG.error("createVmfsOnVmware error:{}", e.toString()); + throw new DmeException(e.getMessage()); + } + return dataStoreStr; + } + /** + * @Description: 获取各个主机所在的主机组id + * @Param hostIds + * @return List + * @throws VcenterException + * @author yc + * @Date 2021/5/20 16:26 + */ + public List getClusterNamesByHostId(List hostIds) throws VcenterException { + //首先判断入参 + ArrayList clusterIds = new ArrayList(); + if (CollectionUtils.isEmpty(hostIds)) + return clusterIds; + List clusteridList = vcsdkUtils.getAllClusterIds(); + //循环主机id,判断主机所属的主机组 + for (String hostid : hostIds) + for (String clusterid : clusteridList) { + List hosts = vcsdkUtils.getHostidsOnCluster(clusterid); + if (!CollectionUtils.isEmpty(hosts) && hosts.contains(hostid)) + clusterIds.add(clusterid); + } + return clusterIds; + } + + /** + * @Description: 检查映射结果,并且分别统计成功和失败的主机或者主机组 + * @Param taskMap + * @return @return + * @throws + * @author yc + * @Date 2021/5/21 16:39 + */ + private Map> checkTaskStatusMappingToHostOrClustre(Map taskMap, + List objHostIds, List clusterIds) throws DmeException { + if (CollectionUtils.isEmpty(taskMap)) { + throw new DmeException("create vmfs: check mapping result,the parmas is error"); + } + Map> mappingResultMap = new HashMap<>(); + List mappedList = new ArrayList<>(); + List unMappedList = new ArrayList<>(); + if (!CollectionUtils.isEmpty(objHostIds)) { + //检查主机集合的映射结果 + for (String hostId : taskMap.keySet()) { + TaskDetailInfo result = taskService.queryTaskById(taskMap.get(hostId)); + if (3 == result.getStatus() && 100 == result.getProgress()) { + mappedList.add(hostId); + } else { + unMappedList.add(hostId); + } + } + //将联通性检测失败的主机也放至映射失败的集合中 + List failList = objHostIds.stream().filter(id -> !taskMap.keySet().contains(id)).collect(Collectors.toList()); + unMappedList.addAll(failList); + mappingResultMap.put("hostMapped", mappedList); + mappingResultMap.put("hostUnmapped", unMappedList); + } else if (!CollectionUtils.isEmpty(clusterIds)) { + //检查主机组集合的映射结果 + for (String clusterId : taskMap.keySet()) { + TaskDetailInfo result = taskService.queryTaskById(taskMap.get(clusterId)); + if (3 == result.getStatus() && 100 == result.getProgress()) { + mappedList.add(clusterId); + } else { + unMappedList.add(clusterId); + } + } + //将联通性检测失败的主机组也放至映射失败的集合中 + List failList = clusterIds.stream().filter(id -> !taskMap.keySet().contains(id)).collect(Collectors.toList()); + unMappedList.addAll(failList); + mappingResultMap.put("clusterMapped", mappedList); + mappingResultMap.put("clusterUnmapped", unMappedList); + } + return mappingResultMap; + } + + /** + * @Description: 根据存储获取映射的lun信息 + * @Param volumeId + * @return List + * @throws DmeException + * @author yc + * @Date 2021/6/2 16:39 + */ + private List findMappedHostsAndClusters(String volumeId) throws DmeException { + if (StringUtils.isEmpty(volumeId)) { + throw new DmeException("findMappedHostsAndClusters error:the param is empty"); + } + //调用dme查询指定lun的详细信息 + String url = DmeConstants.DME_VOLUME_BASE_URL + "/" + volumeId; + ResponseEntity responseEntity; + try { + responseEntity = dmeAccessService.access(url, HttpMethod.GET, null); + + } catch (Exception e) { + throw new DmeException("findMappedHostsAndClusters error :response " + e.getMessage()); + } + if (responseEntity.getStatusCodeValue() != HttpStatus.OK.value()) { + LOG.error("queryTaskById failed!taskId={},errorMsg:{}", volumeId, responseEntity.getBody()); + throw new DmeException("findMappedHostsAndClusters error :response error"); + } + //解析响应结果,获取lun所映射的主机和主机组信息 + JsonObject jsonObject = new JsonParser().parse(responseEntity.getBody().toString()).getAsJsonObject(); + //String response = responseEntity.getBody(); + JsonObject volumeDetail = new JsonObject(); + if (!StringUtils.isEmpty(jsonObject)) { + volumeDetail = jsonObject.get("volume").getAsJsonObject(); + } + List attachmentList = new ArrayList<>(); + + JsonArray attachments = volumeDetail.get("attachments").getAsJsonArray(); + for (JsonElement jsonElement1 : attachments) { + Attachment attachment = new Attachment(); + JsonObject json1 = jsonElement1.getAsJsonObject(); + attachment.setId(ToolUtils.getStr(json1.get(ID_FIELD))); + attachment.setVolumeId(ToolUtils.getStr(json1.get("volume_id"))); + attachment.setHostId(ToolUtils.getStr(json1.get(HOST_ID))); + attachment.setAttachedAt(ToolUtils.getStr(json1.get("attached_at"))); + attachment.setAttachedHostGroup(ToolUtils.getStr(json1.get("attached_host_group"))); + attachment.setAttachedAtDate(ToolUtils.getDate(ToolUtils.getStr(json1.get("attached_at")))); + attachmentList.add(attachment); + } + + return attachmentList; + } + + /** + * @return @return + * @throws + * @Description: 向指定主机组中添加主机(主机支持批量) + * @Param hostGroupId, hostIds + * @author yc + * @Date 2021/6/4 10:04 + */ + private void addHostsToHostGroupbatch(String hostGroupId, List hostIds) throws DmeException { + //校验参数 + if (StringUtils.isEmpty(hostGroupId) || CollectionUtils.isEmpty(hostIds) || hostIds.size() > 100) { + throw new DmeException("add hosts to host group error,the param is empty"); + } + + Map> reqMap = new HashMap<>(); + String url = DmeConstants.PUT_ADD_HOST_TO_HOSTS.replace("{hostgroup_id}", StringUtil.dealQuotationMarks(hostGroupId)); + reqMap.put("host_ids", hostIds); + ResponseEntity responseEntity; + try { + responseEntity = dmeAccessService.access(url, HttpMethod.PUT, gson.toJson(reqMap)); + }catch (Exception e){ + throw new DmeException("add hosts to host group error"+e.getMessage()); + } + if (responseEntity.getStatusCodeValue() != HttpStatus.OK.value()) { + throw new DmeException("add hosts to host group error"); + } + } + /** + * @return @boolean + * @throws DmeException + * @Description: 将主机移出主机组 + * @Param hostGroupId, hostIds + * @author yc + * @Date 2021/6/4 18:08 + */ + private boolean removeHostFromHostgroupNew(@NotNull String hostGroupId, @NotNull List hostIds) throws DmeException { + + Map params = new HashMap<>(); + + String url = DmeConstants.PUT_REMOVE_HOST_FROM_HOSTGROUP.replace("{hostgroup_id}", hostGroupId); + params.put("host_ids", hostIds); + params.put("sync_to_storage", true); + ResponseEntity responseEntity; + try { + responseEntity = dmeAccessService.access(url, HttpMethod.PUT, gson.toJson(params)); + } catch (Exception e) { + throw new DmeException("request DME remove host from hostgroup failed!" + e.getMessage()); + } + if (responseEntity.getStatusCodeValue() != HttpStatus.OK.value()) { + throw new DmeException("remove host from hostgroup failed!{}", + hostIds + " from " + hostGroupId); + } + return isRemoveHostOfHostgroup(hostGroupId); + + } + /** + * @return @return + * @throws + * @Description: 检查主机组和集群的一致性 + * @Param @param null + * @author yc + * @Date 2021/5/31 17:21 + */ + public HostGroupAndClusterConsistency checkConsistencyAndGetclusterId(String clusterId,String hostGroupVolumid) throws DmeException { + //校验集群id(clusterId)不能为空 + if (StringUtils.isEmpty(clusterId)) { + throw new DmeException("check consistency error : the clusterId is empty!"); + } + //首先根据集群id获取集群信息 + String prefix = vcsdkUtils.getVcConnectionHelper().objectId2Mor(clusterId).getValue(); + List> dmeHostGroupList = new ArrayList<>(); + List> dmeHostGroups = dmeAccessService.getDmeHostGroups(prefix); + //根据集群的名称和主机数量查询主机,对查询出的主机组进行筛选 + String vmwarehosts = vcsdkUtils.getHostsOnCluster(clusterId); + if (StringUtils.isEmpty(vmwarehosts)) { + new DmeException("the cluster has no host"); + } + List> vmwarehostlists = gson.fromJson(vmwarehosts, + new TypeToken>>() { + }.getType()); + //todo 20210621 修改挂载集群时映射主机组时需要剔除已经隐射的主机 + List mappedHostid = new ArrayList<>(); + if(!StringUtils.isEmpty(hostGroupVolumid)) { + Map>> allHabs = getAllInitionator(); + List attachmentList = findMappedHostsAndClusters(hostGroupVolumid); + if (!CollectionUtils.isEmpty(attachmentList)) { + for (Attachment attach : attachmentList) { + if (!StringUtils.isEmpty(StringUtil.dealQuotationMarks(attach.getHostId()))) { + mappedHostid.add(StringUtil.dealQuotationMarks(attach.getHostId())); + } + } + } + //从集群中的主机中剔除已经映射的主机 + vmwarehostlists = deleteMappedHost(vmwarehostlists,mappedHostid,allHabs); + } + + //循环dme上的集群的主机组,获取和集群中主机数量相等的主机组; + if (!CollectionUtils.isEmpty(dmeHostGroups)) { + List> finalVmwarehostlists = vmwarehostlists; + dmeHostGroupList = dmeHostGroups.stream().filter(hostGroupMap -> (int) hostGroupMap.get("host_count") == finalVmwarehostlists.size()).collect(Collectors.toList()); + } + //校验DME中的启动器是否包含vcenter,如果包含默认为两者为同一集群 + //1.根据集群中主机的获取主机对应的启动器(Vcenter侧) + Map>> hbas = new HashMap<>(); + for (Map hostMap : vmwarehostlists ){ + List> hosthbas = vcsdkUtils.getHbasByHostObjectId(hostMap.get(HOSTID)); + hbas.put(hostMap.get(HOSTID),hosthbas); + // Map sss = vcsdkUtils.getHbaByHostObjectId(hostMap.get(HOSTID)); + + } + /* Map>> hbas = vcsdkUtils.getHbasByClusterObjectId2(clusterId);//获取name\ + if (!StringUtils.isEmpty(hostGroupVolumid)) { + //todo 20210621 修改挂载集群时映射主机组时需要剔除已经隐射的主机 + deleteMappedHostHabs(mappedHostid, hbas,); + }*/ + ArrayList hbaList = new ArrayList(); + if (!CollectionUtils.isEmpty(hbas)) { + //准备一个Boolean类型的set用于判断启动器相等判断的最后结果 + for (String hostId : hbas.keySet()) { + if (!CollectionUtils.isEmpty(hbas.get(hostId))) { + hbas.get(hostId).forEach(hba -> { + hbaList.add((String) hba.get("name")); + }); + } + } + } + List hbaListTemp = hbaList.stream().filter(Objects::nonNull).collect(Collectors.toList()); + //2.Dme侧获取启动器 + if (!CollectionUtils.isEmpty(dmeHostGroupList)) { + for (Map dmeHostGroupMap : dmeHostGroupList) { + //1.查询主机数量相等的主机组中的主机,根据主机获取主机对应的启动器(DME侧) + String hostGroupId = null; + List initiators = new ArrayList<>(); + if (!CollectionUtils.isEmpty(dmeHostGroupMap)) { + hostGroupId = (String) dmeHostGroupMap.get(ID_FIELD); + } + //2.根据主机组id获取主机,并且获取主机的启动器 + if (!StringUtils.isEmpty(hostGroupId)) { + List> hostList = dmeAccessService.getDmeHostInHostGroup(hostGroupId); + //2.1.根据主机获取主机的所有启动器 + if (!CollectionUtils.isEmpty(hostList)) { + for (Map dmehost : hostList) { + // 得到主机的启动器 + if (!CollectionUtils.isEmpty(dmehost)) { + String demHostId = ToolUtils.getStr(dmehost.get(ID_FIELD)); + List> subinitiators = dmeAccessService.getDmeHostInitiators(demHostId); + LOG.info("initiators of host on dme!", + gson.toJson(initiators) + "host size:" + initiators.size()); + if (!CollectionUtils.isEmpty(subinitiators)) { + subinitiators.stream().forEach(s -> { + initiators.add((String) s.get(PORT_NAME)); + }); + } + } + } + } + } + List initiatorsTemp = initiators.stream().filter(Objects::nonNull).collect(Collectors.toList()); + if (initiatorsTemp.containsAll(hbaListTemp)) { + return new HostGroupAndClusterConsistency(true, hostGroupId); + } + } + } + return new HostGroupAndClusterConsistency(false); + } + + private void deleteMappedHostHabs(List mappedHostid, Map>> hbas) throws DmeException{ + //根据已经映射的hostid查询主机对应的ip地址, + List ipList = new ArrayList<>(); + if(!CollectionUtils.isEmpty(mappedHostid)){ + for (String hostid : mappedHostid) { + Map dmeHostImfo = dmeAccessService.getDmeHost(hostid); + if (!StringUtils.isEmpty(dmeHostImfo) && !StringUtils.isEmpty(dmeHostImfo.get(IP_FIELD))){ + ipList.add(ToolUtils.getStr(dmeHostImfo.get(IP_FIELD))); + } + } + } + Map>> mappedHbas = new HashMap<>(); + //获取vcenter侧的所有主机信息,获取主机ip相同的 + List> allHost = vcsdkUtils.getAllHosts2(); + if (!CollectionUtils.isEmpty(allHost)){ + for (Map hostInfo : allHost) { + if (!CollectionUtils.isEmpty(hostInfo) && ipList.contains( hostInfo.get("hostName"))){ + hbas.remove(hostInfo.get("hostName")); + } + } + } + } + + private List> deleteMappedHost(List> vmwarehostlists, List mappedHostid, + Map>> allHabs) throws DmeException{ + //循环vcenter端的主机列表,查找主机ip所对应的dme端的hostid + List> vmwareHosts = new ArrayList<>(); + if (!CollectionUtils.isEmpty(vmwarehostlists)){ + for (Map hostMap : vmwarehostlists) { + if (!CollectionUtils.isEmpty(hostMap) && !StringUtils.isEmpty(hostMap.get(HOSTID))){ + String hostResult = getDmeHostId(hostMap.get(HOSTID),allHabs); + if (StringUtils.isEmpty(hostResult)){ + throw new DmeException("get hostid from dme return empty"); + } + if (!mappedHostid.contains(hostResult)){ + vmwareHosts.add(hostMap); + } + } + } + } + return vmwareHosts; + + } + private Map deleteMappedHost2(List targList, List mappedHostid,Map>> allHbas ) throws DmeException{ + //循环vcenter端的主机列表,查找主机ip所对应的dme端的hostid + Map vmwareHosts = new HashMap<>(); + if (!CollectionUtils.isEmpty(targList)){ + for (String hostid : targList) { + if (!StringUtils.isEmpty(hostid)){ + String hostResult = getDmeHostId(hostid,allHbas); + if (StringUtils.isEmpty(hostResult)){ + throw new DmeException("get hostid from dme return empty"); + } + if (!mappedHostid.contains(hostResult)){ + vmwareHosts.put(hostid,hostResult); + } + } + } + } + return vmwareHosts; + + } + + private String getDmeHostId(String hostid, Map>> allHbas) throws DmeException { + if (StringUtils.isEmpty(hostid)) { + throw new DmeException("get dme host id error"); + } + List> hbas = vcsdkUtils.getHbasByHostObjectId(hostid); + if (CollectionUtils.isEmpty(hbas)) { + throw new DmeException("The" + hostid + " did not find a valid Hba"); + } + List wwniqns = new ArrayList<>(); + for (Map hba : hbas) { + wwniqns.add(ToolUtils.getStr(hba.get(NAME_FIELD))); + } + for (String dmehostid : allHbas.keySet()) { + List> hostinitionators = allHbas.get(dmehostid); + if (hostinitionators != null && hostinitionators.size() > 0) { + for (Map inimap : hostinitionators) { + String portName = ToolUtils.getStr(inimap.get(PORT_NAME)); + if (wwniqns.contains(portName)) { + return dmehostid; + + } + } + } + } + return null; + } + /** + * @return hostIds + * @throws DmeException + * @Description: 检查主机或者主机组是否存在,不存在就创建新的主机或者主机组 + * @Param params, allinitionators, volumeId, deviceTypeSet + * @author yc + * @Date 2021/5/13 14:54 + */ + private Map> checkOrCreateToHostorHostGroupNew(Map params, + Map>> allinitionators, + String volumeId, HashSet deviceTypeSet, + List> chooseDevicelists) throws DmeException { + // 根据前端入参,确定主机和主机组的组合方式(chooseDevice) + //去重后根据前端入参的方式进行逻辑判断 + //1.单纯选择主机的方式创建 + Map hostIdMap = new HashMap<>(); + Map> hostIds = new HashMap<>(); + + try { + if (deviceTypeSet.contains("host")) { + //检查以主机的方式创建,多主机是否属于同一主机组,不支持多主机组的形式 + checkHostsBelongOnecluster(chooseDevicelists); + //检查主机是否存在,不存在就创建新的主机 + Map hostIdMaps = getHostNameAndHostIdList(chooseDevicelists); + List objIds = checkOrCreateToHostNew(hostIdMaps, allinitionators); + // 根据获取到的dme主机,检查主机连通性 + List failHostIdList = estimateConnectivityOfHostOrHostgroupNew(ToolUtils.getStr(params.get(STORAGE_ID)), objIds, null); + // 连通性正常的主机或者主机组id + if (CollectionUtils.isEmpty(failHostIdList)) { + hostIds.put("nomalHost", objIds); + } + } + //2.单纯选择主机组的方式创建 + else if (deviceTypeSet.contains("cluster")) { + //todo 重新改造原有方法(检查主机组连通性) + //检查主机组是否存在,不存在就创建新的主机组 + List clusters = getClusterIdList(chooseDevicelists); + if (!CollectionUtils.isEmpty(clusters) && clusters.size() >1 ){ + throw new DmeException("create vmfs params is error"); + } + List objIds = getOrCreateHostGroupIdNew(clusters, volumeId); + List failGroupHostIdList = new ArrayList<>(); + // 检查主机组连通性 + if (!CollectionUtils.isEmpty(objIds)) { + for (String hostGroupId : objIds) { + failGroupHostIdList.addAll(estimateConnectivityOfHostOrHostgroupNew(ToolUtils.getStr(params.get(STORAGE_ID)), null, hostGroupId)); + } + } + if (CollectionUtils.isEmpty(hostIdMap)) { + hostIds.put("nomalCluster", objIds); + } + } + else { + throw new DmeException("create vmfs deviceType is error"); + } + + } catch (DmeException e) { + LOG.error("checkOrcreateToHostorHostGroup error:", e); + throw new DmeException(e.getMessage()); + } + return hostIds; + } + /** + * @Description: 查询存储设备的创建方式 + * @Param dataStoreObjectIds + * @return String + * @throws + * @author yc + * @Date 2021/6/2 15:31 + */ + @Override + public String queryCreationMethodByDatastore(String dataStoreObjectId) throws DmeException { + + //根据存储设备获取设备上映射的卷信息 + String result = null; + if(StringUtils.isEmpty(dataStoreObjectId)){ + throw new DmeException("query creation method by datastore error,param is empty"); + } + String volumeId = null; + DmeVmwareRelation dvr = dmeVmwareRalationDao.getDmeVmwareRelationByDsId(dataStoreObjectId); + if (!StringUtils.isEmpty(dvr)) { + volumeId = dvr.getVolumeId(); + } + if (StringUtils.isEmpty(volumeId)){ + throw new DmeException("get volumeid fail"); + } + //查询指定lun,获取映射信息 + List attachmentList = findMappedHostsAndClusters(volumeId); + //获取映射数据中时间最早的映射方式 + if (CollectionUtils.isEmpty(attachmentList)){ + throw new DmeException("query lun info error"); + } + Attachment mindatares = attachmentList.stream().min(Comparator.comparing(attachment -> attachment.getAttachedAtDate())).get(); + //判断时间最小的映射方式(如果为主机组,就返回‘cluster’,如果为主机返回‘host’,其他报错) + if (!StringUtils.isEmpty(mindatares.getAttachedHostGroup()) && !mindatares.getAttachedHostGroup().equalsIgnoreCase("null")){ + result = CLUSTER; + } else if (!StringUtils.isEmpty(mindatares.getHostId()) && !mindatares.getHostId().equalsIgnoreCase("null")){ + result = HOST; + } + if(StringUtils.isEmpty(result)){ + throw new DmeException("query vmfs create method error"); + } + return result; + } } diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/services/VmfsOperationServiceImpl.java b/dmestore-service/src/main/java/com/huawei/dmestore/services/VmfsOperationServiceImpl.java index 53590723f..55d676d3b 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/services/VmfsOperationServiceImpl.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/services/VmfsOperationServiceImpl.java @@ -1,5 +1,6 @@ package com.huawei.dmestore.services; +import com.google.gson.reflect.TypeToken; import com.huawei.dmestore.constant.DmeConstants; import com.huawei.dmestore.constant.DpSqlFileConstants; import com.huawei.dmestore.dao.DmeVmwareRalationDao; @@ -31,7 +32,7 @@ /** * VmfsOperationService * - * @author lianqiang + * @author lianqiangN * @since 2020-09-09 **/ public class VmfsOperationServiceImpl implements VmfsOperationService { @@ -41,8 +42,6 @@ public class VmfsOperationServiceImpl implements VmfsOperationService { private static final String CODE_403 = "403"; - private static final String CODE_20883 = "20883"; - private static final String CODE_503 = "503"; private static final String TASK_ID = "task_id"; @@ -51,6 +50,8 @@ public class VmfsOperationServiceImpl implements VmfsOperationService { private static final String LUN_ADD_CAPACITY = "lunAddCapacity"; + private static final String HOSTID = "hostId"; + private DmeAccessService dmeAccessService; @Autowired private DmeStorageService dmeStorageService; @@ -269,9 +270,13 @@ public void expandVmfs2(Map volumemap) throws DmeException { try { //扩容条件判断。 Map sectors = compareCapacityForExpandLun(addCapacity, datastoreobjid); + if (CollectionUtils.isEmpty(sectors)) { + LOG.error("get current vmfs datastore capacity failed!{}", datastoreobjid); + throw new DmeException("get current vmfs datastore capacity failed!{}", datastoreobjid); + } Long changedSector = sectors.get(CHANGE_SECTOR); Long addcapacity = sectors.get(LUN_ADD_CAPACITY); - if (addcapacity != null && changedSector != null) { + if (addcapacity != null) { String lunAddCapacity = ToolUtils.getStr(addcapacity); //DME Lun当前容量不满足扩容vmfs存储条件,扩容Lun volumemap.put("vo_add_capacity", lunAddCapacity); @@ -289,10 +294,22 @@ public void expandVmfs2(Map volumemap) throws DmeException { if (!taskService.checkTaskStatus(taskIds)) { throw new DmeException(CODE_503, "expand volume failed !"); } + /*String listStr = vcsdkUtils.getHostsByDsObjectId(datastoreobjid, true); + if (!StringUtils.isEmpty(listStr)) { + List> hosts = gson.fromJson(listStr, + new TypeToken>>() { + }.getType()); + for (Map host : hosts) { + String hostId = ToolUtils.getStr(host.get(HOSTID)); + vcsdkUtils.scanDataStore(null, hostId); + } + }*/ } - String result = vcsdkUtils.expandVmfsDatastore2(changedSector, datastoreobjid); - if ("failed".equals(result)) { - throw new DmeException(CODE_403, "expand vmfsDatastore failed !"); + if (changedSector != null) { + String result = vcsdkUtils.expandVmfsDatastore2(changedSector, datastoreobjid); + if ("failed".equals(result)) { + throw new DmeException(CODE_403, "expand vmfsDatastore failed !"); + } } // 刷新vCenter存储 vcsdkUtils.refreshDatastore(datastoreobjid); @@ -331,18 +348,20 @@ private Map compareCapacityForExpandLun(int addCapacity,String stor Long totalCurrentSector = sectors.get(ToolUtils.TOTAL_END_SECTOR); Long changedSector = addSector + currentEndSector; int lunAddCapacity = addCapacity; - if (Long.compare(totalCurrentSector, changedSector) != -1) { - sectors.put(CHANGE_SECTOR, changedSector); - } else if (Long.compare(totalCurrentSector, changedSector) == -1 && Long.compare(totalCurrentSector, currentEndSector) != -1) { - int available = (int)Math.floor((totalCurrentSector - currentEndSector) * ToolUtils.DISK_SECTOR_SIZE / ToolUtils.GI); - if (Long.compare(available, 1) != -1) { - lunAddCapacity -= available; + if (totalCurrentSector != null) { + if (Long.compare(totalCurrentSector, changedSector) != -1) { sectors.put(CHANGE_SECTOR, changedSector); - sectors.put(LUN_ADD_CAPACITY, Long.valueOf(lunAddCapacity)); - } else { + } else if (Long.compare(totalCurrentSector, changedSector) == -1 && Long.compare(totalCurrentSector, currentEndSector) != -1) { + int available = (int) Math.floor((totalCurrentSector - currentEndSector) * ToolUtils.DISK_SECTOR_SIZE / ToolUtils.GI); + if (Long.compare(available, 1) != -1) { + lunAddCapacity -= available; + } sectors.put(CHANGE_SECTOR, changedSector); sectors.put(LUN_ADD_CAPACITY, Long.valueOf(lunAddCapacity)); } + } else { + sectors.put(CHANGE_SECTOR, changedSector); + sectors.put(LUN_ADD_CAPACITY, Long.valueOf(lunAddCapacity)); } } return sectors; diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/services/VmwareAccessService.java b/dmestore-service/src/main/java/com/huawei/dmestore/services/VmwareAccessService.java index 4ca2aa811..906fb99c7 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/services/VmwareAccessService.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/services/VmwareAccessService.java @@ -3,6 +3,7 @@ import com.huawei.dmestore.entity.DmeVmwareRelation; import com.huawei.dmestore.exception.DmeException; import com.huawei.dmestore.exception.DmeSqlException; +import com.huawei.dmestore.model.ClusterTree; import java.util.List; import java.util.Map; @@ -109,4 +110,32 @@ List> getMountDataStoresByClusterObjectId(String clusterObje * @throws DmeSqlException DmeSqlException */ DmeVmwareRelation getDmeVmwareRelationByDsId(String storeId) throws DmeSqlException; + /** + * @Description: get cluster tree + * @Param @param null + * @return @return + * @throws DmeException + * @author yc + * @Date 2021/5/11 14:21 + */ + List listclustersReturnTree() throws DmeException; + /** + * @Description: 挂载页面查询可挂载的主机和集群信息 + * @Param @param null + * @return @return + * @throws + * @author yc + * @Date 2021/5/14 9:47 + */ + List getClustersAndHostsByDsObjectIdNew(String dataStoreObjectId) throws DmeException; + /** + * @Description: 查询独立主机 + * @Param @param null + * @return @return + * @throws + * @author yc + * @Date 2021/6/7 16:53 + */ + List listHostsAndClusterReturnTree() throws DmeException; + } diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/services/VmwareAccessServiceImpl.java b/dmestore-service/src/main/java/com/huawei/dmestore/services/VmwareAccessServiceImpl.java index 685b2d3e0..5849388a0 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/services/VmwareAccessServiceImpl.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/services/VmwareAccessServiceImpl.java @@ -5,6 +5,7 @@ import com.huawei.dmestore.exception.DmeException; import com.huawei.dmestore.exception.DmeSqlException; import com.huawei.dmestore.exception.VcenterException; +import com.huawei.dmestore.model.ClusterTree; import com.huawei.dmestore.utils.ToolUtils; import com.huawei.dmestore.utils.VCSDKUtils; @@ -13,9 +14,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -30,12 +35,20 @@ public class VmwareAccessServiceImpl implements VmwareAccessService { private static final String OBJECT_ID = "objectId"; + private static final String HOST_ID = "hostId"; + + private static final String HOST_NAME = "hostName"; + private Gson gson = new Gson(); private DmeVmwareRalationDao dmeVmwareRalationDao; private VCSDKUtils vcsdkUtils; + @Autowired + private VmfsAccessService vmfsAccessService; + + public VCSDKUtils getVcsdkUtils() { return vcsdkUtils; } @@ -245,4 +258,339 @@ public List> getMountDataStoresByClusterObjectId(String clus public DmeVmwareRelation getDmeVmwareRelationByDsId(String storeId) throws DmeSqlException { return dmeVmwareRalationDao.getDmeVmwareRelationByDsId(storeId); } -} + + /** + * @Description: 获取集群和集群下的主机集合以树的形式返回 + * @Param @param null + * @return @return + * @throws DmeException + * @author yc + * @Date 2021/5/11 15:59 + */ + @Override + public List listclustersReturnTree() throws DmeException { + List clusterTreeList = new ArrayList<>(); + List> lists = new ArrayList<>(); + try { + String listStr = vcsdkUtils.getAllClusters(); + if (!StringUtils.isEmpty(listStr)) { + lists = gson.fromJson(listStr, new TypeToken>>() { }.getType()); + } + if(!CollectionUtils.isEmpty(lists)){ + for (Map map : lists) { + ClusterTree clusterTree = new ClusterTree(); + String vmwarehosts = vcsdkUtils.getHostsOnCluster(map.get("clusterId")); + List> vmwarehostlists = new ArrayList<>(); + if (!StringUtils.isEmpty(vmwarehosts)) { + vmwarehostlists = gson.fromJson(vmwarehosts, + new TypeToken>>() { + }.getType()); + } + clusterTree.setClusterId(map.get("clusterId")); + clusterTree.setClusterName(map.get("clusterName")); + if(!CollectionUtils.isEmpty(getHostList(vmwarehostlists))) { + clusterTree.setChildren(getHostList(vmwarehostlists)); + } + //clusterTree.setChildren(Collections.singletonList(vmwarehostlists)); + clusterTreeList.add(clusterTree); + } + //根据获取到的集群列表取得集群下的所有主机 + + } + } catch (VcenterException e) { + LOG.error("list listClusters error:", e); + throw new DmeException(e.getMessage()); + } + return clusterTreeList; + } + + /** + * @Description: 将主机集合循环添加至树中 + * @Param @param null + * @return @return + * @author yc + * @Date 2021/5/11 15:58 + */ + public List getHostList(List> vmwarehostlists) { + List clusterTreeList = new ArrayList<>(); + if (!CollectionUtils.isEmpty(vmwarehostlists)){ + for (Map map : vmwarehostlists) { + ClusterTree clusterTree = new ClusterTree(); + clusterTree.setClusterId(map.get("hostId")); + clusterTree.setClusterName(map.get("hostName")); + clusterTreeList.add(clusterTree); + } + } + return clusterTreeList; + } + + public List getMountableHostList(List> vmwarehostlists,List mountedHostId ) { + List clusterTreeList = new ArrayList<>(); + if (!CollectionUtils.isEmpty(vmwarehostlists)){ + for (Map map : vmwarehostlists) { + ClusterTree clusterTree = new ClusterTree(); + clusterTree.setClusterId(map.get("hostId")); + clusterTree.setClusterName(map.get("hostName")); + if (!CollectionUtils.isEmpty(mountedHostId) && mountedHostId.contains(map.get("hostId"))) { + clusterTree.setFlag(false); + }else { + clusterTree.setFlag(true); + } + clusterTreeList.add(clusterTree); + } + } + return clusterTreeList; + } + /** + * @Description: 挂载页面查询可挂载的主机和集群 + * @Param @param null + * @return @return + * @throws + * @author yc + * @Date 2021/5/14 9:47 + */ + @Override + public List getClustersAndHostsByDsObjectIdNew(String dataStoreObjectId) throws DmeException { + List mountedHostId = null; + List clusteridList = new ArrayList<>(); + List> hostList = new ArrayList<>(); + List> clusterList = new ArrayList<>(); + List treeList = new ArrayList<>(); + try { + //1.根据存储查询已经挂载的主机 + mountedHostId = vcsdkUtils.getAllMountedHostId(dataStoreObjectId); + //2.获取所有主机 + //3.获取所有集群 + // 取得vcenter中的所有host。 + String hostListStr = vcsdkUtils.getAllHosts(); + if (!StringUtils.isEmpty(hostListStr)) { + hostList = gson.fromJson(hostListStr, new TypeToken>>() { + }.getType()); + } + String clusterListStr = vcsdkUtils.getAllClusters(); + if (!StringUtils.isEmpty(clusterListStr)) { + clusterList = gson.fromJson(clusterListStr, new TypeToken>>() { + }.getType()); + if (!CollectionUtils.isEmpty(clusterList)){ + for (Map map : clusterList) { + clusteridList.add(map.get("clusterId")); + } + } + } + } catch (Exception e) { + LOG.error("get all mountable hosts and clusters by datastoreobjectid error:", e); + throw new DmeException("get all mountable hosts and clusters by datastoreobjectid error:" + e.getMessage()); + } + //4.循环获取的主机,剔除已经挂载的主机 + Map> temp = new HashMap<>(); + if (!CollectionUtils.isEmpty(hostList)) { + temp = getHostTempList(hostList); + //todo 查询主机是否属于集群,如果属于集群就不返回,或者主机在已挂载的主机集合中就不返回 + for (Map hostidMap : hostList) { + if (!CollectionUtils.isEmpty(clusteridList)) { + for (String clusterid : clusteridList) { + List hosts = vcsdkUtils.getHostidsOnCluster(clusterid); + if (!CollectionUtils.isEmpty(hosts) && hosts.contains(hostidMap.get(HOST_ID))){ + // || (!CollectionUtils.isEmpty(mountedHostId) && mountedHostId.contains(hostidMap.get(HOST_ID)))) { + temp.remove(hostidMap.get(HOST_ID)); + } + } + } + } + } + if (!CollectionUtils.isEmpty(temp)) { + for (String key : temp.keySet()) { + ClusterTree clusterTree = new ClusterTree(); + clusterTree.setClusterId(temp.get(key).get(HOST_ID)); + clusterTree.setClusterName(temp.get(key).get(HOST_NAME)); + if(!CollectionUtils.isEmpty(mountedHostId) && mountedHostId.contains(temp.get(key).get(HOST_ID))) { + clusterTree.setFlag(false); + }else { + clusterTree.setFlag(true); + } + treeList.add(clusterTree); + } + } + //处理集群,从集群的主机中剔除已经挂载的主机 + if (!CollectionUtils.isEmpty(clusterList)) { + for (Map map : clusterList) { + ClusterTree clusterTree = new ClusterTree(); + String vmwarehosts = vcsdkUtils.getHostsOnCluster(map.get("clusterId")); + List> vmwarehostlists = new ArrayList<>(); + if (!StringUtils.isEmpty(vmwarehosts)) { + vmwarehostlists = gson.fromJson(vmwarehosts, + new TypeToken>>() { + }.getType()); + } + if (!CollectionUtils.isEmpty(vmwarehostlists)) { + temp = getHostTempList(vmwarehostlists); + /* for (Map hostMap : vmwarehostlists) { + if (!CollectionUtils.isEmpty(mountedHostId) && mountedHostId.contains(hostMap.get(HOST_ID))) { + temp.remove(hostMap.get(HOST_ID)); + } + }*/ + List> tempHostInfo = new ArrayList<>(temp.values()); + List hostListTmp = getMountableHostList(tempHostInfo,mountedHostId); + if (!CollectionUtils.isEmpty(hostListTmp)) { + clusterTree.setClusterId(map.get("clusterId")); + clusterTree.setClusterName(map.get("clusterName")); + clusterTree.setChildren(CollectionUtils.isEmpty(hostListTmp) ? null : hostListTmp); + boolean flag = getFlag(hostListTmp); + clusterTree.setFlag(flag); + + } + if (!StringUtils.isEmpty(clusterTree.getClusterId())) { + treeList.add(clusterTree); + } + } + } + } + + return treeList; + } + + private boolean getFlag(List hostListTmp) { + boolean flag = false; + if (!CollectionUtils.isEmpty(hostListTmp)){ + for (ClusterTree clusterTree : hostListTmp) { + if( clusterTree.isFlag()){ + return true; + } + } + } + return flag; + } + + /** + * @Description: 获取可挂载的主机数据 + * @Param @param null + * @return @return + * @throws + * @author yc + * @Date 2021/6/8 10:21 + */ + private List getMountableHostsByDsObjectId (String dataStoreObjectId) throws DmeException { + List clusterTreeList = new ArrayList<>(); + List> lists = null; + try { + String listStr = vcsdkUtils.getHostsByDsObjectId(dataStoreObjectId); + if (!StringUtils.isEmpty(listStr)) { + lists = gson.fromJson(listStr, new TypeToken>>() { }.getType()); + } + } catch (VcenterException e) { + LOG.error("get Hosts By DsObjectId error:", e); + throw new DmeException(e.getMessage()); + } + if (CollectionUtils.isEmpty(lists)){ + throw new DmeException("get Hosts By DsObjectId error"); + } + for (Map hostMap : lists) { + ClusterTree clusterTree = new ClusterTree(); + clusterTree.setClusterId(hostMap.get(HOST_ID)); + clusterTree.setClusterName(hostMap.get(HOST_NAME)); + if (!StringUtils.isEmpty(clusterTree.getClusterId())){ + clusterTreeList.add(clusterTree); + } + } + return clusterTreeList; + } + /** + * @Description: 创建vmfs时,以树的方式返回可用的主机和集群 + * @Param @param null + * @return @return + * @throws + * @author yc + * @Date 2021/6/7 17:32 + */ + @Override + public List listHostsAndClusterReturnTree() throws DmeException { + List treeList = new ArrayList<>(); + List> hostList = new ArrayList<>(); + List> clusterList = new ArrayList<>(); + List clusteridList = null; + try { + // 取得vcenter中的所有host。 + String hostListStr = vcsdkUtils.getAllHosts(); + clusteridList = vcsdkUtils.getAllClusterIds(); + if (!StringUtils.isEmpty(hostListStr)) { + hostList = gson.fromJson(hostListStr, new TypeToken>>() { + }.getType()); + } + String clusterListStr = vcsdkUtils.getAllClusters(); + if (!StringUtils.isEmpty(clusterListStr)) { + clusterList = gson.fromJson(clusterListStr, new TypeToken>>() { + }.getType()); + } + //获取独立主机 + //准备暂存集合 + Map> temp = new HashMap<>(); + if (!CollectionUtils.isEmpty(hostList)) { + temp = getHostTempList(hostList); + //todo 查询主机是否属于集群,如果属于集群就不返回 + for (Map hostidMap : hostList) { + if (!CollectionUtils.isEmpty(clusteridList)) { + for (String clusterid : clusteridList) { + List hosts = vcsdkUtils.getHostidsOnCluster(clusterid); + if (!CollectionUtils.isEmpty(hosts) && hosts.contains(hostidMap.get(HOST_ID))) { + temp.remove(hostidMap.get(HOST_ID)); + } + } + } + } + } + if (!CollectionUtils.isEmpty(temp)) { + for (String key : temp.keySet()) { + ClusterTree clusterTree = new ClusterTree(); + clusterTree.setClusterId(temp.get(key).get(HOST_ID)); + clusterTree.setClusterName(temp.get(key).get(HOST_NAME)); + treeList.add(clusterTree); + } + } + //处理集群 + if (!CollectionUtils.isEmpty(clusterList)) { + for (Map map : clusterList) { + ClusterTree clusterTree = new ClusterTree(); + String vmwarehosts = vcsdkUtils.getHostsOnCluster(map.get("clusterId")); + List> vmwarehostlists = new ArrayList<>(); + if (!StringUtils.isEmpty(vmwarehosts)) { + vmwarehostlists = gson.fromJson(vmwarehosts, + new TypeToken>>() { + }.getType()); + } + List hostListTmp = getHostList(vmwarehostlists); + if (!CollectionUtils.isEmpty(hostListTmp)) { + clusterTree.setClusterId(map.get("clusterId")); + clusterTree.setClusterName(map.get("clusterName")); + clusterTree.setChildren(hostListTmp); + } + if (!StringUtils.isEmpty(clusterTree.getClusterId())) { + treeList.add(clusterTree); + } + } + } + } catch (Exception e) { + LOG.error("list hosts And clusters return tree error:", e); + throw new DmeException(e.getMessage()); + } + return treeList; + } + /** + * @Description: 获取暂存主机集合对象 + * @Param @param null + * @return @return + * @throws + * @author yc + * @Date 2021/6/7 18:44 + */ + private Map> getHostTempList(List> hostList) { + Map> temp = new HashMap<>(); + if (!CollectionUtils.isEmpty(hostList)) { + for (Map hostidMap : hostList) { + String hostId = hostidMap.get(HOST_ID); + temp.put(hostId,hostidMap); + } + } + return temp; + } + +} \ No newline at end of file diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/utils/StringUtil.java b/dmestore-service/src/main/java/com/huawei/dmestore/utils/StringUtil.java index 01924d784..1b2a83ea1 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/utils/StringUtil.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/utils/StringUtil.java @@ -1,5 +1,7 @@ package com.huawei.dmestore.utils; +import org.springframework.util.StringUtils; + import java.nio.charset.Charset; @@ -44,4 +46,12 @@ public static boolean isBlank(String str) { public static boolean isNotBlank(String str) { return !isBlank(str); } + + public static String dealQuotationMarks(String str){ + String result = null; + if (!StringUtils.isEmpty(str) && str.startsWith("\"") && str.endsWith("\"")){ + result = str.substring(1, str.length() - 1); + } + return result; + } } diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/utils/ToolUtils.java b/dmestore-service/src/main/java/com/huawei/dmestore/utils/ToolUtils.java index a26509ac3..ea3e46f88 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/utils/ToolUtils.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/utils/ToolUtils.java @@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; +import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import jdk.internal.dynalink.beans.StaticClass; @@ -469,4 +470,33 @@ public static Float jsonToFloat2(JsonElement obj) { } return re; } + /** + * @Description: 处理从接口接受的时间的格式 + * @Param dateValue + * @return Date + * @author yc + * @Date 2021/6/3 9:50 + */ + public static Date getDate(String dateValue) { + //处理传入的时间字符串对多余的”“ + String dateStr = null; + if (!StringUtils.isEmpty(dateValue) && dateValue.startsWith("\"") && dateValue.endsWith(("\""))){ + dateStr = dateValue.substring(1, dateValue.length() - 1); + } + if(dateStr.contains("T")) { + dateStr = dateStr.replace("T"," "); + } + Date date = null; + + if (StringUtils.isEmpty(dateStr)){ + return date; + } + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS"); + try { + date = sdf.parse(dateStr); + } catch (ParseException e) { + LOG.error("getDate error:{}", e.toString()); + } + return date; + } } diff --git a/dmestore-service/src/main/java/com/huawei/dmestore/utils/VCSDKUtils.java b/dmestore-service/src/main/java/com/huawei/dmestore/utils/VCSDKUtils.java index 203a0d948..31bdd0b39 100644 --- a/dmestore-service/src/main/java/com/huawei/dmestore/utils/VCSDKUtils.java +++ b/dmestore-service/src/main/java/com/huawei/dmestore/utils/VCSDKUtils.java @@ -55,6 +55,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -319,6 +320,41 @@ public String getAllHosts() throws VcenterException { return listStr; } + /** + * 得到所有主机的ID与name + * + * @return String + * @throws VcenterException VcenterException + */ + public List> getAllHosts2() throws VcenterException { + logger.info("get all hosts start"); + List> lists = new ArrayList<>(); + try { + VmwareContext[] vmwareContexts = vcConnectionHelpers.getAllContext(); + for (VmwareContext context : vmwareContexts) { + RootFsMo rootFsMo = rootVmwareMoFactory.build(context, context.getRootFolder()); + List> hosts = rootFsMo.getAllHostOnRootFs(); + if (hosts != null && hosts.size() > 0) { + for (Pair host : hosts) { + HostMo host1 = hostVmwareFactory.build(context, host.first()); + Map map = new HashMap<>(); + String objectId = vcConnectionHelpers.mor2ObjectId(host1.getMor(), context.getServerAddress()); + map.put(HOST_ID, objectId); + map.put(OBJECT_ID, objectId); + map.put(HOST_NAME, host1.getName()); + lists.add(map); + } + } + } + } catch (Exception e) { + logger.error("getAllHosts error:{}", e.getMessage()); + throw new VcenterException(e.getLocalizedMessage()); + } + logger.info("get all hosts end"); + return lists; + } + + public String findHostById(String objectId) throws VcenterException { String hostlist = ""; try { @@ -370,6 +406,30 @@ public String getAllClusters() throws VcenterException { } return listStr; } + /** + * @Description: 获取所有集群id + + * @Date 2021/5/20 16:17 + */ + public List getAllClusterIds() throws VcenterException { + ArrayList clusetids = new ArrayList(); + try { + VmwareContext[] vmwareContexts = vcConnectionHelpers.getAllContext(); + for (VmwareContext vmwareContext : vmwareContexts) { + RootFsMo rootFsMo = rootVmwareMoFactory.build(vmwareContext, vmwareContext.getRootFolder()); + List> cls = rootFsMo.getAllClusterOnRootFs(); + if (cls != null && cls.size() > 0) for (Pair cl : cls) { + ClusterMo cl1 = clusterVmwareMoFactory.build(vmwareContext, cl.first()); + String objectId = vcConnectionHelpers.mor2ObjectId(cl1.getMor(), vmwareContext.getServerAddress()); + clusetids.add(objectId); + } + } + } catch (Exception e) { + logger.error("getAllClusters error:{}", e.getMessage()); + throw new VcenterException(e.getMessage()); + } + return clusetids; + } /** * 得到所有主机的ID与name 除去已经挂载了当前存储的主机 20200918objectId @@ -884,7 +944,7 @@ public String getMountDataStoresByClusterObjectId(String clusterObjectId, String } } } catch (Exception ex) { - logger.error("vmware getMountDataStore by slusterObjI derror:{}", ex.getMessage()); + logger.error("vmware getMountDataStore by slusterObjI derror:{}", ex.getMessage()); throw ex; } return listStr; @@ -927,6 +987,36 @@ public String getHostsOnCluster(String clusterObjectId) throws VcenterException return listStr; } + + /** + * 得到指定集群下的所有主机 20200918objectId + * + * @param clusterObjectId clusterObjectId + * @return String + * @throws VcenterException VcenterException + */ + public List getHostidsOnCluster(String clusterObjectId) throws VcenterException { + List hostIds = new ArrayList<>(); + try { + // 得到当前的context + String serverguid = vcConnectionHelpers.objectId2Serverguid(clusterObjectId); + VmwareContext context = vcConnectionHelpers.getServerContext(serverguid); + ManagedObjectReference clmor = vcConnectionHelpers.objectId2Mor(clusterObjectId); + ClusterMo cl1 = clusterVmwareMoFactory.build(context, clmor); + List> hosts = cl1.getClusterHosts(); + if (hosts != null && hosts.size() > 0) { + for (Pair host : hosts) { + HostMo host1 = hostVmwareFactory.build(context, host.first()); + String objectId = vcConnectionHelpers.mor2ObjectId(host1.getMor(), context.getServerAddress()); + hostIds.add(objectId); + } + } + } catch (Exception e) { + logger.error(e.getMessage()); + throw new VcenterException(e.getMessage()); + } + return hostIds; + } /** * 得到指定集群下的所有主机,以及指定主机所属集群下的所有主机 20200918objectId * @@ -1124,9 +1214,8 @@ public String expandVmfsDatastore(String dsname, Integer addCapacity, String dat /** * expand oriented datastore capacity * - * @param dsname dsname - * @param addCapacity addCapacity - * @param dataStoreObjectId dataStoreObjectId + * @param changeSector + * @param dataStoreObjectId * @return String */ public String expandVmfsDatastore2(Long changeSector, String dataStoreObjectId) { @@ -1223,25 +1312,23 @@ public Map queryVmfsDeviceCapacity(String storeObjectId){ if (host1 != null && hdsMo != null && hostStorageSystemMo != null) { ManagedObjectReference dataStoreMor = vcConnectionHelpers.objectId2Mor(storeObjectId); DatastoreMo dsMo = datastoreVmwareMoFactory.build(vmwareContext, dataStoreMor); + //vmfs存储所在的设备名称 + VmfsDatastoreInfo vmfsDatastoreInfo = dsMo.getVmfsDatastoreInfo(); + HostScsiDiskPartition extent = vmfsDatastoreInfo.getVmfs().getExtent().get(0); + String deviceName = DISK_BASE_PATH + extent.getDiskName(); + //vmfs当前容量分区信息 + List deviceNames = new ArrayList<>(); + deviceNames.add(deviceName); + HostDiskPartitionInfo hostDiskPartitionInfo = hostStorageSystemMo.retrieveDiskPartitionInfo(deviceNames).get(0); + long currentEndSector = hostDiskPartitionInfo.getSpec().getPartition().get(0).getEndSector(); + sectors.put(ToolUtils.CURRENT_END_SECTOR, currentEndSector); List vmfsDatastoreOptions = hdsMo.queryVmfsDatastoreExpandOptions(dsMo); if (vmfsDatastoreOptions != null && vmfsDatastoreOptions.size() > 0) { - //vmfs存储所在的设备名称 - VmfsDatastoreInfo vmfsDatastoreInfo = dsMo.getVmfsDatastoreInfo(); - HostScsiDiskPartition extent = vmfsDatastoreInfo.getVmfs().getExtent().get(0); - String deviceName = DISK_BASE_PATH + extent.getDiskName(); - //vmfs当前容量分区信息 - List deviceNames = new ArrayList<>(); - deviceNames.add(deviceName); - HostDiskPartitionInfo hostDiskPartitionInfo = hostStorageSystemMo.retrieveDiskPartitionInfo(deviceNames).get(0); - long currentEndSector = hostDiskPartitionInfo.getSpec().getPartition().get(0).getEndSector(); //vmfs所在设备总分区信息 VmfsDatastoreOption vmfsDatastoreOption = vmfsDatastoreOptions.get(0); VmfsDatastoreExpandSpec spec = (VmfsDatastoreExpandSpec) vmfsDatastoreOption.getSpec(); long totalEndSector = spec.getPartition().getPartition().get(0).getEndSector(); - sectors.put(ToolUtils.CURRENT_END_SECTOR, currentEndSector); sectors.put(ToolUtils.TOTAL_END_SECTOR, totalEndSector); - } else { - logger.error("query vmfs Datastore Options error!{}", vmfsDatastoreOptions.size()); } } else { logger.info("host1 is null:{}, hdsMo is null:{}", host1 == null, hdsMo == null); @@ -1856,16 +1943,33 @@ public String attachTag(String datastoreType, String datastoreId, String service public boolean deleteVmfsDataStore(String datastoreobjectid) throws VcenterException { boolean isDelete = false; try { - VmwareContext[] vmwareContexts = vcConnectionHelpers.getAllContext(); - for (VmwareContext vmwareContext : vmwareContexts) { - RootFsMo rootFsMo = rootVmwareMoFactory.build(vmwareContext, vmwareContext.getRootFolder()); - List> hosts = rootFsMo.getAllHostOnRootFs(); - if (hosts != null && hosts.size() > 0) { - for (Pair host : hosts) { - HostMo host1 = hostVmwareFactory.build(vmwareContext, host.first()); + + String serverguid = vcConnectionHelpers.objectId2Serverguid(datastoreobjectid); + VmwareContext vmwareContext = vcConnectionHelpers.getServerContext(serverguid); + ManagedObjectReference dataStoreMor = vcConnectionHelpers.objectId2Mor(datastoreobjectid); + DatastoreMo datastoreMo = new DatastoreMo(vmwareContext, dataStoreMor); + + List hostMounts = datastoreMo.getHostMounts(); + List mounthostids = new ArrayList<>(); + if (!CollectionUtils.isEmpty(hostMounts)) { + for (DatastoreHostMount dhm : hostMounts) { + if (dhm.getMountInfo() != null && dhm.getMountInfo().isMounted()) { + mounthostids.add(dhm.getKey().getValue()); + } + } + } + + RootFsMo rootFsMo = rootVmwareMoFactory.build(vmwareContext, vmwareContext.getRootFolder()); + List> hosts = rootFsMo.getAllHostOnRootFs(); + if (hosts != null && hosts.size() > 0) { + for (Pair host : hosts) { + HostMo host1 = hostVmwareFactory.build(vmwareContext, host.first()); + if (!CollectionUtils.isEmpty(mounthostids) && mounthostids.contains(host1.getMor().getValue())) { HostDatastoreSystemMo hdsMo = host1.getHostDatastoreSystemMo(); - if (null != datastoreobjectid) { - isDelete = hdsMo.deleteDatastore(vcConnectionHelpers.objectId2Mor(datastoreobjectid)); + VmfsDatastoreInfo datastoreInfo = (VmfsDatastoreInfo) hdsMo.getDatastoreInfo(dataStoreMor); + if (null != datastoreInfo) { + String name = datastoreMo.getVmfsDatastoreInfo().getName(); + isDelete = hdsMo.deleteDatastore(hdsMo.findDatastore(name)); break; } } @@ -1954,6 +2058,74 @@ public void mountVmfsOnCluster(String datastoreStr, String clusterObjectId, Stri throw new VcenterException(e.getMessage()); } } + public void mountVmfsOnClusterNew(String datastoreStr, String clusterObjectId, String hostObjectId) + throws VcenterException { + if (StringUtils.isEmpty(datastoreStr)) { + logger.info("datastoreStr is null"); + return; + } + if (StringUtils.isEmpty(hostObjectId) && StringUtils.isEmpty(clusterObjectId)) { + logger.info("host:{} and cluster:{} is null", hostObjectId, clusterObjectId); + return; + } + Map dsmap = gson.fromJson(datastoreStr, new TypeToken>() { }.getType()); + String objHostName = ""; + String objDataStoreName = ""; + if (dsmap != null) { + objHostName = ToolUtils.getStr(dsmap.get(HOST_NAME)); + objHostName = objHostName == null ? "" : objHostName; + objDataStoreName = ToolUtils.getStr(dsmap.get(NAME)); + } + try { + String serverguid = null; + if (!StringUtils.isEmpty(clusterObjectId)) { + serverguid = vcConnectionHelpers.objectId2Serverguid(clusterObjectId); + } else if (!StringUtils.isEmpty(hostObjectId)) { + serverguid = vcConnectionHelpers.objectId2Serverguid(hostObjectId); + } + if (StringUtils.isEmpty(serverguid)) { + logger.error("mountVmfsOnCluster serverguid is null"); + throw new VcenterException("mount vmfs on cluster error!serverguid is null"); + } + VmwareContext vmwareContext = vcConnectionHelpers.getServerContext(serverguid); + if (!StringUtils.isEmpty(clusterObjectId)) { + logger.info("mount Vmfs to Cluster begin"); + // 集群下的所有主机 + List> hosts = getHostsOnCluster(clusterObjectId, hostObjectId); + if (hosts != null && hosts.size() > 0) { + for (Pair host : hosts) { + try { + HostMo host1 = hostVmwareFactory.build(vmwareContext, host.first()); + logger.info("Host under Cluster: {}", host1.getName()); + + // 只挂载其它的主机 + if (host1 != null && !objHostName.equals(host1.getName())) { + mountVmfsNew(objDataStoreName, host1); + } + } catch (Exception e) { + logger.error("mount Vmfs On Cluster error:{}", e.getMessage()); + } + } + } + } else if (!StringUtils.isEmpty(hostObjectId)) { + try { + logger.info("mount Vmfs to host begin"); + ManagedObjectReference objmor = vcConnectionHelpers.objectId2Mor(hostObjectId); + HostMo hostmo = hostVmwareFactory.build(vmwareContext, objmor); + + // 只挂载其它的主机 + if (hostmo != null && !objHostName.equals(hostmo.getName())) { + mountVmfsNew(objDataStoreName, hostmo); + } + } catch (Exception e) { + logger.error("mount Vmfs On Cluster error:{}", e.getMessage()); + } + } + } catch (Exception e) { + logger.error("mount Vmfs On Cluster error:", e); + throw new VcenterException(e.getMessage()); + } + } /** * 将vmfs从主机或集群上卸载 @@ -2071,6 +2243,42 @@ public void mountVmfs(String datastoreName, HostMo hostMo) { } } + public void mountVmfsNew(String datastoreName, HostMo hostMo) { + try { + if (StringUtils.isEmpty(datastoreName)) { + logger.info("datastore Name is null"); + return; + } + if (hostMo == null) { + logger.info("host info is null"); + return; + } + + // 挂载前重新扫描datastore + logger.info("refreshStorageSystem before mount Vmfs!"); + hostMo.getHostStorageSystemMo().refreshStorageSystem(); + + // 查询目前未挂载的卷 + for (HostFileSystemMountInfo mount : hostMo.getHostStorageSystemMo() + .getHostFileSystemVolumeInfo() + .getMountInfo()) { + if (mount.getVolume() instanceof HostVmfsVolume && datastoreName.equals(mount.getVolume().getName())) { + HostVmfsVolume volume = (HostVmfsVolume) mount.getVolume(); + + // 挂载卷 + hostMo.getHostStorageSystemMo().mountVmfsVolume(volume.getUuid()); + logger.info("mount Vmfs success!"); + } + } + + // 挂载后重新扫描datastore + logger.info("refreshStorageSystem after mount Vmfs!"); + hostMo.getHostStorageSystemMo().refreshStorageSystem(); + } catch (Exception e) { + logger.error(" mount vmfs volume error!datastoreName={},error:{}", datastoreName, e.getMessage()); + } + } + /** * 卸载存储 20201016objectId * @@ -3788,4 +3996,285 @@ public String satpRuleProcess(String hostObjectId, VCenterInfo vcenterinfo, Stri } + /** + * @return @return + * @throws + * @Description: 将vmfs从主机或者主机组上移除 + * @Param @param null + * @author yc + * @Date 2021/5/18 9:48 + */ + public void unmountVmfsOnHostOrClusterNew(String datastoreStr, List clusterObjectIds, List hostObjectIds) + throws VcenterException { + + try { + if (StringUtils.isEmpty(datastoreStr)) { + logger.info("unmountVmfs datastore datastoreStr is null"); + return; + } + if (CollectionUtils.isEmpty(clusterObjectIds) && CollectionUtils.isEmpty(hostObjectIds)) { + logger.info("unmountVmfs host hostObjectId and clusterObjectId is null"); + return; + } + Map dsmap = gson.fromJson(datastoreStr, new TypeToken>() { + }.getType()); + String objHostName = ""; + String objDataStoreName = ""; + if (dsmap != null) { + objHostName = ToolUtils.getStr(dsmap.get(HOST_NAME)); + objHostName = objHostName == null ? "" : objHostName; + objDataStoreName = ToolUtils.getStr(dsmap.get(NAME)); + } + //new design by yc need to ajusting to collection + if (!CollectionUtils.isEmpty(clusterObjectIds)) { + for (String clusterObjectId : clusterObjectIds) { + String serverguid = null; + serverguid = vcConnectionHelpers.objectId2Serverguid(clusterObjectId); + if (!StringUtils.isEmpty(serverguid)) { + VmwareContext vmwareContext = vcConnectionHelpers.getServerContext(serverguid); + if (!StringUtils.isEmpty(clusterObjectId)) { + // 集群下的所有主机 + List> hosts = getHostsOnCluster(clusterObjectId, null); + if (hosts == null && hosts.size() == 0) { + return; + } + for (Pair host : hosts) { + try { + HostMo host1 = hostVmwareFactory.build(vmwareContext, host.first()); + // 从挂载的主机卸载 + if (host1 != null && objHostName.equals(host1.getName())) { + unmountVmfs(objDataStoreName, host1); + } + } catch (Exception e) { + logger.error("unmount Vmfs On Cluster error:", e); + } + } + } + } + } + } + if (!CollectionUtils.isEmpty(hostObjectIds)) { + for (String hostObjectId : hostObjectIds) { + String serverguid = null; + serverguid = vcConnectionHelpers.objectId2Serverguid(hostObjectId); + if (!StringUtils.isEmpty(serverguid)) { + VmwareContext vmwareContext = vcConnectionHelpers.getServerContext(serverguid); + if (!StringUtils.isEmpty(hostObjectId)) { + try { + ManagedObjectReference objmor = vcConnectionHelpers.objectId2Mor(hostObjectId); + HostMo hostmo = hostVmwareFactory.build(vmwareContext, objmor); + + // 从挂载的主机卸载 + if (hostmo != null) { + unmountVmfs(objDataStoreName, hostmo); + } + } catch (Exception e) { + logger.error("mount Vmfs On Cluster error:", e); + } + } + } + } + } + } catch (Exception e) { + logger.error("unmount Vmfs On Cluster error:", e); + throw new VcenterException(e.getMessage()); + } + } + + /** + * @return @return + * @throws + * @Description: scanDataStore be designed by yc again, ajusted to the param is collections + * @Param @param null + * @author yc + * @Date 2021/5/18 10:03 + */ + public void scanDataStoreNew(List clusterObjectIds, List hostObjectIds) throws VcenterException { + try { + if (!CollectionUtils.isEmpty(clusterObjectIds)) { + for (String clusterObjectId : clusterObjectIds) { + String serverguid = null; + serverguid = vcConnectionHelpers.objectId2Serverguid(clusterObjectId); + if (!StringUtils.isEmpty(serverguid)) { + VmwareContext vmwareContext = vcConnectionHelpers.getServerContext(serverguid); + // 集群下的所有主机 + List> hosts = null; + if (!StringUtils.isEmpty(clusterObjectId)) { + hosts = getHostsOnCluster(clusterObjectId, null); + if (hosts != null && hosts.size() > 0) { + for (Pair host : hosts) { + try { + HostMo host1 = hostVmwareFactory.build(vmwareContext, host.first()); + logger.info("Host under Cluster: {}", host1.getName()); + host1.getHostStorageSystemMo().rescanVmfs(); + } catch (Exception ex) { + logger.error("under Cluster scan Data Store error:{}", ex.getMessage()); + } + } + } + } + } + } + } + if (!CollectionUtils.isEmpty(hostObjectIds)) { + for (String hostObjectId : hostObjectIds) { + String serverguid = null; + serverguid = vcConnectionHelpers.objectId2Serverguid(hostObjectId); + if (!StringUtils.isEmpty(serverguid)) { + VmwareContext vmwareContext = vcConnectionHelpers.getServerContext(serverguid); + if (!StringUtils.isEmpty(hostObjectId)) { + try { + ManagedObjectReference objmor = vcConnectionHelpers.objectId2Mor(hostObjectId); + HostMo hostmo = hostVmwareFactory.build(vmwareContext, objmor); + hostmo.getHostStorageSystemMo().rescanVmfs(); + } catch (Exception ex) { + logger.error("scan Data Store error:{}", ex.getMessage()); + } + } + } + } + } + } catch (Exception e) { + logger.error("scan Data Store error:", e); + throw new VcenterException(e.getMessage()); + } + } + /** + * @Description: 获取当前存储已经挂载的所有主机ID + * @Param @param null + * @return @return + * @throws + * @author yc + * @Date 2021/6/8 10:57 + */ + public List getAllMountedHostId(String dataStoreObjectId) throws Exception { + DatastoreMo dsmo = null; + List> hosts = new ArrayList<>(); + List hostObjIds = new ArrayList<>(); + VmwareContext vmwareContext = null; + try { + // 得到当前的context + String serverguid = vcConnectionHelpers.objectId2Serverguid(dataStoreObjectId); + vmwareContext = vcConnectionHelpers.getServerContext(serverguid); + RootFsMo rootFsMo = rootVmwareMoFactory.build(vmwareContext, vmwareContext.getRootFolder()); + hosts = rootFsMo.getAllHostOnRootFs(); + ManagedObjectReference dsmor = vcConnectionHelpers.objectId2Mor(dataStoreObjectId); + + // 取得该存储下所有已经挂载的主机ID + dsmo = datastoreVmwareMoFactory.build(vmwareContext, dsmor); + } catch (Exception e) { + logger.error("get mounted host info error:{}", e.getMessage()); + throw new VcenterException("get mounted host info error:" + e.getMessage()); + } + List mounthostids = new ArrayList<>(); + if (!StringUtils.isEmpty(dsmo)) { + List dhms = dsmo.getHostMounts(); + if (!CollectionUtils.isEmpty(dhms)) { + for (DatastoreHostMount dhm : dhms) { + if (dhm.getMountInfo() != null && dhm.getMountInfo().isMounted()) { + mounthostids.add(dhm.getKey().getValue()); + } + } + } + } + if (!CollectionUtils.isEmpty(mounthostids) && !CollectionUtils.isEmpty(hosts)){ + for (String host : mounthostids){ + for (Pair hostPair : hosts) { + if( host.equalsIgnoreCase( hostPair.first().getValue())){ + HostMo host1 = hostVmwareFactory.build(vmwareContext, hostPair.first()); + String objectId = vcConnectionHelpers.mor2ObjectId(host1.getMor(), vmwareContext.getServerAddress()); + hostObjIds.add(objectId); + } + } + } + } + return hostObjIds; + } + /** + * @Description: 根据集群id获取集群名称 + * @Param @param null + * @return @return + * @throws + * @author yc + * @Date 2021/6/8 16:21 + */ + public String getClusterNameByClusterId(String clusterId) throws VcenterException { + String clusterName = null; + List> clusterList = new ArrayList<>(); + String clusterListStr = getAllClusters(); + if (!StringUtils.isEmpty(clusterListStr)) { + clusterList = gson.fromJson(clusterListStr, new TypeToken>>() { + }.getType()); + } + if(!CollectionUtils.isEmpty(clusterList)){ + for (Map clusterMap : clusterList) { + if( clusterId.equalsIgnoreCase(clusterMap.get(CLUSTER_ID))) { + clusterName = clusterMap.get(CLUSTER_NAME); + } + if (!StringUtils.isEmpty(clusterName)){ + return clusterName; + } + } + } + return clusterName; + } + + public List> getClustersByDsObjectIdNew(String dataStoreObjectId) throws VcenterException { + String listStr = ""; + List> lists = new ArrayList<>(); + try { + String serverguid = vcConnectionHelpers.objectId2Serverguid(dataStoreObjectId); + VmwareContext vmwareContext = vcConnectionHelpers.getServerContext(serverguid); + RootFsMo rootFsMo = rootVmwareMoFactory.build(vmwareContext, vmwareContext.getRootFolder()); + + // 取得该存储下所有已经挂载的主机ID + List mounthostids = new ArrayList<>(); + ManagedObjectReference dsmor = vcConnectionHelpers.objectId2Mor(dataStoreObjectId); + DatastoreMo dsmo = datastoreVmwareMoFactory.build(vmwareContext, dsmor); + if (dsmo != null) { + List dhms = dsmo.getHostMounts(); + if (dhms != null && dhms.size() > 0) { + for (DatastoreHostMount dhm : dhms) { + if (dhm.getMountInfo() != null && dhm.getMountInfo().isMounted()) { + mounthostids.add(dhm.getKey().getValue()); + } + } + } + } + + /** + * 取得所有集群,并通过mounthostids进行过滤,过滤掉已经挂载的主机 + * 扫描集群下所有主机,只要有一个主机没挂当前存储就要显示,只有集群下所有主机都挂载了该存储就不显示 + */ + List> cls = rootFsMo.getAllClusterOnRootFs(); + if (cls != null && cls.size() > 0) { + for (Pair cl : cls) { + boolean isMount = false; + ClusterMo cl1 = clusterVmwareMoFactory.build(vmwareContext, cl.first()); + List> hosts = cl1.getClusterHosts(); + if (hosts != null && hosts.size() > 0) { + for (Pair host : hosts) { + HostMo host1 = hostVmwareFactory.build(vmwareContext, host.first()); + if (mounthostids.contains(host1.getMor().getValue())) { + isMount = true; + break; + } + } + } + if (isMount) { + Map map = new HashMap<>(); + String objectId = vcConnectionHelpers.mor2ObjectId(cl1.getMor(), + vmwareContext.getServerAddress()); + map.put(CLUSTER_ID, objectId); + map.put(CLUSTER_NAME, cl1.getName()); + lists.add(map); + } + } + } + } catch (Exception e) { + logger.error("getClustersByDsObjectId error:{}", e.getMessage()); + throw new VcenterException(e.getMessage()); + } + return lists; + } } diff --git a/dmestore-service/src/main/java/com/huawei/vmware/mo/HostDatastoreSystemMo.java b/dmestore-service/src/main/java/com/huawei/vmware/mo/HostDatastoreSystemMo.java index 6d0b0c157..0678f8621 100644 --- a/dmestore-service/src/main/java/com/huawei/vmware/mo/HostDatastoreSystemMo.java +++ b/dmestore-service/src/main/java/com/huawei/vmware/mo/HostDatastoreSystemMo.java @@ -3,20 +3,7 @@ import com.huawei.vmware.util.VmwareContext; import com.google.gson.Gson; -import com.vmware.vim25.DatastoreInfo; -import com.vmware.vim25.HostNasVolumeSecurityType; -import com.vmware.vim25.HostNasVolumeSpec; -import com.vmware.vim25.HostScsiDisk; -import com.vmware.vim25.ManagedObjectReference; -import com.vmware.vim25.NasDatastoreInfo; -import com.vmware.vim25.ObjectContent; -import com.vmware.vim25.ObjectSpec; -import com.vmware.vim25.PropertyFilterSpec; -import com.vmware.vim25.PropertySpec; -import com.vmware.vim25.TraversalSpec; -import com.vmware.vim25.VmfsDatastoreCreateSpec; -import com.vmware.vim25.VmfsDatastoreExpandSpec; -import com.vmware.vim25.VmfsDatastoreOption; +import com.vmware.vim25.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -130,6 +117,33 @@ public boolean deleteDatastore(ManagedObjectReference datastoreMor) throws Excep return false; } + public ManagedObjectReference findDatastore(String name) throws Exception { + // added Apache CloudStack specific name convention, we will use custom field "cloud.uuid" as datastore name as well + CustomFieldsManagerMo cfmMo = new CustomFieldsManagerMo(context, context.getServiceContent().getCustomFieldsManager()); + int key = cfmMo.getCustomFieldKey("Datastore", CustomFieldConstants.CLOUD_UUID); + assert (key != 0); + + List ocs = getDatastorePropertiesOnHostDatastoreSystem(new String[] {"name", String.format("value[%d]", key)}); + if (ocs != null) { + for (ObjectContent oc : ocs) { + if (oc.getPropSet().get(0).getVal().equals(name)) + return oc.getObj(); + + if (oc.getPropSet().size() > 1) { + DynamicProperty prop = oc.getPropSet().get(1); + if (prop != null && prop.getVal() != null) { + if (prop.getVal() instanceof CustomFieldStringValue) { + String val = ((CustomFieldStringValue)prop.getVal()).getValue(); + if (val.equalsIgnoreCase(name)) + return oc.getObj(); + } + } + } + } + } + return null; + } + /** * createNfsDatastore * diff --git a/dmestore-ui/src/main/angular/src/app/app.helpers.ts b/dmestore-ui/src/main/angular/src/app/app.helpers.ts index 47679cfb7..dc4bbf101 100644 --- a/dmestore-ui/src/main/angular/src/app/app.helpers.ts +++ b/dmestore-ui/src/main/angular/src/app/app.helpers.ts @@ -1,6 +1,11 @@ import { AbstractControl } from '@angular/forms'; +import { ClrSelectedState } from '@clr/angular'; import { ValidatorFn } from '@angular/forms'; import { FormControl, ValidationErrors } from '@angular/forms'; +import { getLodash } from './shared/lib'; +import { host } from '@angular-devkit/build-angular/src/test-utils'; + +export const _ = getLodash(); export const handleRes = (res, successOptions, faildOptions?) => { if (res.code === '200') { @@ -202,7 +207,10 @@ export function isStringLengthByteOutRange(nameString, limit = 27, name = 'byte' const element = nameString.charAt(index); if (regExpCollection.chinise().test(element)) { length = length + 2; - console.log( '🚀 ~ file: app.helpers.ts ~ line 197 ~ isStringLengthByteOutRange ~ length', length ); + console.log( + '🚀 ~ file: app.helpers.ts ~ line 197 ~ isStringLengthByteOutRange ~ length', + length + ); } } return length > limit; @@ -210,12 +218,16 @@ export function isStringLengthByteOutRange(nameString, limit = 27, name = 'byte' export function formatCapacity(c: number, isGB: boolean) { let cNum; - if (c < 1024) { - cNum = isGB ? c.toFixed(3) + 'GB' : c.toFixed(3) + 'MB'; - } else if (c >= 1024 && c < 1048576) { - cNum = isGB ? (c / 1024).toFixed(3) + 'TB' : (c / 1024).toFixed(3) + 'GB'; - } else if (c >= 1048576) { - cNum = isGB ? (c / 1024 / 1024).toFixed(3) + 'PB' : (c / 1024 / 1024).toFixed(3) + 'TB'; + try { + if (c < 1024) { + cNum = isGB ? c.toFixed(3) + 'GB' : c.toFixed(3) + 'MB'; + } else if (c >= 1024 && c < 1048576) { + cNum = isGB ? (c / 1024).toFixed(3) + 'TB' : (c / 1024).toFixed(3) + 'GB'; + } else if (c >= 1048576) { + cNum = isGB ? (c / 1024 / 1024).toFixed(3) + 'PB' : (c / 1024 / 1024).toFixed(3) + 'TB'; + } + } catch (error) { + console.error(error); } return cNum; } @@ -251,3 +263,191 @@ export function CustomValidatorFaild(checkFn: any): ValidatorFn { return checkFn(control.value) ? { custom: { value: control.value } } : null; }; } + +export type VMFS_CLUSTER_NODE = { + clusterId: string; + clusterName: string; + children?: any[]; + selected?: number; +}; + +export function vmfsGetSelectedFromTree(clusterArray: VMFS_CLUSTER_NODE[], mountType = '') { + let result = []; + let selectedCluster: any = false; + /* 一旦选择一个集群,只能该集权 */ + /* 一旦选择一个主机,只能该主机所在集群 */ + for (const clusterNode of clusterArray) { + let _node: any = clusterNode; + + if (String(clusterNode.selected) === String(ClrSelectedState.SELECTED)) { + /* 第一层本身是host */ + if ((clusterNode as any).deviceType === 'host') { + (_node as any) = _.omit(clusterNode, ['children']); + result.push(_node); + } else if (mountType === 'host') { + /* 创建方式是host */ + (_node as any) = clusterNode; + } else { + /* 创建方式是集群 */ + /* 集群下有主机是false,以主机方式 */ + const someFalse = _.some( clusterNode?.children, hostNode => String(hostNode.flag) === 'false' ); + if (someFalse) { + (_node as any) = _.omit(clusterNode, ['children']); + result.push(_node); + } else { + (_node as any) = clusterNode; + } + } + } + + /* 通过控制children来限制是否传主机 */ + if (_node.children && _node.children.length > 0) { + for (const hostNode of _node.children) { + if (String(hostNode.selected) === String(ClrSelectedState.SELECTED)) { + if (hostNode.flag !== false) { + const _node = _.omit(hostNode, ['children']); + if (!selectedCluster) { + selectedCluster = clusterNode; + } + result.push(_node); + } + } + } + } + } + return result; +} + +/** + * @Description vmfs 集群 主机 树 第一层是集群 第二层是主机 + * 选了集群只传集群, + * + * @date 2021-05-12 + * @param {any} clusterArray:VMFS_CLUSTER_NODE[] + * @returns {any} + */ +export function getSelectedFromTree( + clusterArray: VMFS_CLUSTER_NODE[], + resType = '', + mountType = '' +) { + let result = []; + let selectedCluster: any = false; + /* 一旦选择一个集群,只能该集权 */ + /* 一旦选择一个主机,只能该主机所在集群 */ + for (const clusterNode of clusterArray) { + if (mountType === 'host') { + if (String(clusterNode.selected) === String(ClrSelectedState.SELECTED)) { + if ((clusterNode as any).deviceType === 'host') { + result.push(_.omit(clusterNode, ['children'])); + } + + if (!selectedCluster) { + selectedCluster = clusterNode; + } + } + } else { + if (String(clusterNode.selected) === String(ClrSelectedState.SELECTED)) { + const _node = _.omit(clusterNode, ['children']); + // _node['deviceType'] = 'cluster'; + result.push(_node); + // console.log(result) + if (!selectedCluster) { + selectedCluster = clusterNode; + } + continue; + } + } + + if (clusterNode.children && clusterNode.children.length > 0) { + for (const hostNode of clusterNode.children) { + if (String(hostNode.selected) === String(ClrSelectedState.SELECTED)) { + const _node = _.omit(hostNode, ['children']); + // _node['deviceType'] = 'host'; + if (!selectedCluster) { + selectedCluster = clusterNode; + } + result.push(_node); + // console.log(result) + } + } + } + } + + const setDisabled = setDisabledTrue => { + /* 需要设置disabled,部分置灰 */ + for (const clusterNode of clusterArray) { + const setOtherDisabled = () => { + (clusterNode as any).isDisabled = true; + if (clusterNode.children && clusterNode.children.length > 0) { + for (const hostNode of clusterNode.children) { + (hostNode as any).isDisabled = true; + } + } + }; + + const setEnable = () => { + (clusterNode as any).isDisabled = false; + if (clusterNode.children && clusterNode.children.length > 0) { + for (const hostNode of clusterNode.children) { + (hostNode as any).isDisabled = false; + } + } + }; + + const setAllEnable = () => { + (clusterNode as any).isDisabled = false; + if (clusterNode.children && clusterNode.children.length > 0) { + for (const hostNode of clusterNode.children) { + (hostNode as any).isDisabled = false; + } + } + }; + + if (setDisabledTrue) { + /* 不同集群,置灰 */ + if (clusterNode.clusterId !== selectedCluster.clusterId) { + setOtherDisabled(); + } else { + /* 相同集群,可选 */ + setEnable(); + } + } else { + /* 全部可选 */ + setAllEnable(); + } + } + }; + + if (resType === 'mount') { + console.log('🚀 ~ file: app.helpers.ts ~ line 353 ~ getSelectedFromTree ~ resType', resType); + } else { + setDisabled(result.length > 0); + } + // console.log(result) + return result; +} + +export function getSelectedFromList(hostArray: VMFS_CLUSTER_NODE[]) { + let result = []; + for (const clusterNode of hostArray) { + if (String(clusterNode.selected) === String(ClrSelectedState.SELECTED)) { + result.push(clusterNode); + continue; + } + } + // console.log(result) + return result; +} + +export function getVmfsCreateTreeFilterBySelect(tree) { + return tree; +} + +export function mockServerData(data, delay = 50) { + return new Promise(resolve => { + setTimeout(() => { + resolve(_.cloneDeep(data) as any[]); + }, delay); + }); +} diff --git a/dmestore-ui/src/main/angular/src/app/routes/common.service.ts b/dmestore-ui/src/main/angular/src/app/routes/common.service.ts index a09330042..ecb084258 100644 --- a/dmestore-ui/src/main/angular/src/app/routes/common.service.ts +++ b/dmestore-ui/src/main/angular/src/app/routes/common.service.ts @@ -2,27 +2,32 @@ import { Injectable } from '@angular/core'; import { ClrDatagridStateInterface } from '@clr/angular'; import * as moment from 'moment'; import { TranslatePipe } from '@ngx-translate/core'; +import { isMockData } from 'mock/mock'; +import { vmfsClusterTreeData } from './../../mock/vmfsClusterTree'; +import { HttpClient } from '@angular/common/http'; +import { getLodash } from '@shared/lib'; +import { mockServerData } from './../app.helpers'; +import { rejects } from 'assert'; +const _ = getLodash(); - +function isSingleHost(node) { + /* 没有children或者children length为0 */ + if (!node.children) return true; + if (_.isArray(node.children) && node.children.length === 0) return true; + return false; +} function getSelectedDateFn(label) { return (minuteName, exp) => { const time = exp.exec(label); const count = Number(time[1]); - return [ - moment().subtract(count, minuteName).valueOf(), - moment().valueOf(), - ]; + return [moment().subtract(count, minuteName).valueOf(), moment().valueOf()]; }; } - @Injectable() export class CommonService { - constructor( - private translatePipe: TranslatePipe - ) { - } + constructor(private translatePipe: TranslatePipe, private http: HttpClient) {} timeSelectorRanges_type1 = [ { value: 'LAST_5_MINUTE', key: 'chart.select.last5Minute' }, @@ -35,7 +40,6 @@ export class CommonService { { value: 'LAST_1_YEAR', key: 'chart.select.last1Year' }, ]; - /* zh:'4小时' , range:'BEGIN_END_TIME', interval: "ONE_MINUTE" begin_time end_time @@ -54,7 +58,6 @@ zh:'一年' ,range:'LAST_1_YEAR', interval: "DAY" { value: 'LAST_1_YEAR', key: 'chart.select.last1Year' }, ]; - /** * @Description 通用的同步翻译工具函数 * @date 2021-04-13 @@ -63,7 +66,7 @@ zh:'一年' ,range:'LAST_1_YEAR', interval: "DAY" */ $t(prop) { const res = this.translatePipe.transform(prop); - return res + return res; } /** @@ -108,7 +111,8 @@ zh:'一年' ,range:'LAST_1_YEAR', interval: "DAY" return info; } - params(query: any = {}) { // 对query进行处理 + params(query: any = {}) { + // 对query进行处理 const p = Object.assign({}, query); return p; } @@ -126,7 +130,7 @@ zh:'一年' ,range:'LAST_1_YEAR', interval: "DAY" // 过滤器 过滤内容 if (state.filters) { for (const filter of state.filters) { - const { property, value } = filter as { property: string, value: string }; + const { property, value } = filter as { property: string; value: string }; query[property] = value; } } @@ -139,4 +143,240 @@ zh:'一年' ,range:'LAST_1_YEAR', interval: "DAY" console.log(qq); return qq; } + + /** + * @Description vmfs 添加 获取主机、集群tree 1. vmfs add 获取所有集群/主机的接口 + * @date 2021-05-13 + * @returns {any} + */ + async remoteGetVmfsDeviceList() { + let data: any = []; + try { + if (isMockData) { + data = await mockServerData(vmfsClusterTreeData); + } else { + const res: any = await new Promise((resolve, reject) => { + this.http + .get('accessvmware/listHostsAndClusterReturnTree', {}) + .subscribe(resolve, reject); + }); + + if (res.code === '200') { + for (let firstNode of res.data) { + if (isSingleHost(firstNode)) { + firstNode.deviceType = 'host'; + } else { + firstNode.deviceType = 'cluster'; + if (firstNode && firstNode.children.length > 0) { + for (let secondNode of firstNode.children) { + if (!secondNode.children) { + secondNode.deviceType = 'host'; + } else { + secondNode.deviceType = 'cluster'; + } + } + } + } + } + data = res.data; + } + } + } catch (error) { + console.log('vmfs 添加 获取主机、集群tree', error); + } finally { + return data; + } + } + + /** + * @Description vmfs 添加 选择的设备是数组 + * @date 2021-05-13 + * @param {any} instance + * @returns {any} + */ + + async remoteCreateVmfs(params) { + if (isMockData) { + // console.log(params); + return { + code: '-99999', + data: { + successNo: 2, + failNo: 1, + connectionResult: ['10.12.22.167'], + descriptionEN: 'loream....', + descriptionCN: '这里有一段内容', + }, + }; + } else { + try { + const res: any = await new Promise((resolve, reject) => { + this.http.post('accessvmfs/createvmfsnew', params).subscribe(resolve, reject); + }); + return res; + } catch (error) { + console.log('vmfs 创建', error); + } + } + } + + /** + * @Description vmfs 挂载 + * @date 2021-05-17 + * @param {any} params + * @returns {any} + */ + async remoteVmfs_Mount(params) { + if (isMockData) { + console.log(params); + return {}; + } else { + try { + const res: any = await new Promise((resolve, reject) => { + this.http.post('/accessvmfs/mountvmfsnew', params).subscribe(resolve, reject); + }); + return res; + } catch (error) { + console.log('vmfs 挂载', error); + } + } + } + /** + * @Description vmfs 挂载 + * @date 2021-05-17 + * @param {any} params + * @returns {any} + */ + async remoteVmfs_Unmount(params) { + if (isMockData) { + console.log(params); + return {}; + } else { + try { + const res: any = await new Promise((resolve, reject) => { + this.http.post('/accessvmfs/ummountvmfsnew', params).subscribe(resolve, reject); + }); + return res; + } catch (error) { + console.log('vmfs 挂载', error); + } + } + } + + /** + * @Description 挂载 获取主机集群列表 + * @param {any} id + * @returns {any} + */ + async remoteGetVmfsDeviceListById_mount(id) { + let data: any = []; + try { + if (isMockData) { + data = await mockServerData(vmfsClusterTreeData); + } else { + const res: any = await new Promise((resolve, reject) => { + this.http + .get(`accessvmware/getClustersAndHostsByDsobjectIdReturnTree?dataStoreObjectId=${id}`) + .subscribe(resolve, reject); + }); + if (res.code === '200') { + for (let firstNode of res.data) { + if (isSingleHost(firstNode)) { + firstNode.deviceType = 'host'; + } else { + firstNode.deviceType = 'cluster'; + if (firstNode && firstNode.children.length > 0) { + for (let secondNode of firstNode.children) { + if (!secondNode.children) { + secondNode.deviceType = 'host'; + } else { + secondNode.deviceType = 'cluster'; + } + } + } + } + } + data = res.data; + } + } + } catch (error) { + console.log('vmfs 添加 获取主机、集群tree', error); + } finally { + return data; + } + } + async remoteGetVmfsDeviceListById_unmount(id) { + let data: any = []; + try { + if (isMockData) { + data = await mockServerData(vmfsClusterTreeData); + } else { + const res: any = await new Promise((resolve, reject) => { + this.http + .get(`accessvmfs/getMountedHostGroupsAndHostReturnTree/${id}`) + .subscribe(resolve, reject); + }); + if (res.code === '200') { + for (let firstNode of res.data) { + if (isSingleHost(firstNode)) { + firstNode.deviceType = 'host'; + } else { + firstNode.deviceType = 'cluster'; + if (firstNode && firstNode.children.length > 0) { + for (let secondNode of firstNode.children) { + if (!secondNode.children) { + secondNode.deviceType = 'host'; + } else { + secondNode.deviceType = 'cluster'; + } + } + } + } + } + data = res.data; + } + } + } catch (error) { + console.log('vmfs 添加 获取主机、集群tree', error); + } finally { + return data; + } + } + + /** + * @Description 挂载 获取选中的挂载类型:主机或者集群 + * @param {any} id + * @returns {string} + */ + async getMountTypeBySeletedId(id) { + let data: string = ''; + try { + if (isMockData) { + // console.log(id); + data = 'host'; + } else { + const res: any = await new Promise((resolve, reject) => { + this.http + .get(`accessvmfs/queryCreationMethodByDatastore?dataStoreObjectId=${id}`) + .subscribe(resolve, reject); + }); + if (res.code === '200') { + data = res.data; + } + } + } catch (error) { + console.log('vmfs获取选中挂载类型', error); + } finally { + return data; + } + } } + +/* +async function getAccessvmwareListclusters(instance) { + + return new Promise((resolve,reject) => { + instance + }) + +} */ diff --git a/dmestore-ui/src/main/angular/src/app/routes/dashboard/dashboard.component.ts b/dmestore-ui/src/main/angular/src/app/routes/dashboard/dashboard.component.ts index 3be19c654..ac2d99853 100644 --- a/dmestore-ui/src/main/angular/src/app/routes/dashboard/dashboard.component.ts +++ b/dmestore-ui/src/main/angular/src/app/routes/dashboard/dashboard.component.ts @@ -143,8 +143,6 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy { /* type 0 :VMFS and NFS, 1:VMFS, 2:NFS */ async loadTop5DataStore(type: string, name: string) { - this.top5dataStoreName = this.translateService.instant(name); - this.top5ShowLoading = true; const handlerGetStoreTopNSuccess = (result: any) => { if (result.code === '200' && result.data && Array.isArray(result.data)) { this.storeageTopN = result.data.map(item => ({ @@ -155,8 +153,11 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy { utilization: item.utilization.toFixed(2), })); } - this.cdr.detectChanges(); + }; + + this.top5dataStoreName = this.translateService.instant(name); + this.top5ShowLoading = true; try { if (isMockData) { @@ -169,6 +170,9 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy { handlerResponseErrorSimple(error); } finally { this.top5ShowLoading = false; + setTimeout(() => { + this.cdr.detectChanges(); + }, 500); } } diff --git a/dmestore-ui/src/main/angular/src/app/routes/nfs/subpages/mount/nfs-mount.component.html b/dmestore-ui/src/main/angular/src/app/routes/nfs/subpages/mount/nfs-mount.component.html index 5a1a631cf..361460cde 100644 --- a/dmestore-ui/src/main/angular/src/app/routes/nfs/subpages/mount/nfs-mount.component.html +++ b/dmestore-ui/src/main/angular/src/app/routes/nfs/subpages/mount/nfs-mount.component.html @@ -3,7 +3,7 @@ @@ -153,7 +153,7 @@ diff --git a/dmestore-ui/src/main/angular/src/app/routes/nfs/subpages/mount/nfs-mount.component.ts b/dmestore-ui/src/main/angular/src/app/routes/nfs/subpages/mount/nfs-mount.component.ts index 0d88e63fa..fe9f45a75 100644 --- a/dmestore-ui/src/main/angular/src/app/routes/nfs/subpages/mount/nfs-mount.component.ts +++ b/dmestore-ui/src/main/angular/src/app/routes/nfs/subpages/mount/nfs-mount.component.ts @@ -171,4 +171,21 @@ export class NfsMountComponent implements OnInit { this.closeModel(); } } +// 控制button是否可选 list和存储 + changeButtonAttrDatastore(){ + if (this.mountForm.hostObjectId&&this.mountForm.hostVkernelIp&&this.mountForm.mountType){ + return false + }else { + return true + } + } + + //控制button是否可选 主机和集群 + changeButtonAttrHostOrCluster(){ + if(this.mountForm.hostVkernelIp&&this.mountForm.dataStoreObjectId&&this.mountForm.mountType){ + return false + }else { + return true + } + } } diff --git a/dmestore-ui/src/main/angular/src/app/routes/rdm/noData.svg b/dmestore-ui/src/main/angular/src/app/routes/rdm/noData.svg new file mode 100644 index 000000000..1ac872821 --- /dev/null +++ b/dmestore-ui/src/main/angular/src/app/routes/rdm/noData.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dmestore-ui/src/main/angular/src/app/routes/rdm/rdm.component.html b/dmestore-ui/src/main/angular/src/app/routes/rdm/rdm.component.html index 62cb57c9f..c50367911 100644 --- a/dmestore-ui/src/main/angular/src/app/routes/rdm/rdm.component.html +++ b/dmestore-ui/src/main/angular/src/app/routes/rdm/rdm.component.html @@ -62,8 +62,9 @@ - + + {{'rdm.storeSet' | translate}} @@ -87,17 +88,23 @@
- {{'rdm.addTips' | translate}} +
{{'rdm.selectOneSer' | translate}}
{{'rdm.createRdmError' | translate}}
+
{{'rdm.storageStrategyNull' | translate}}
+
+
+ {{'tips.noData'|translate}} +
{{item.name}} - + + @@ -380,6 +387,7 @@ {{'menu.cancel' | translate}}{{'menu.previous' | translate}}{{'menu.ok' | translate}} + diff --git a/dmestore-ui/src/main/angular/src/app/routes/rdm/rdm.component.scss b/dmestore-ui/src/main/angular/src/app/routes/rdm/rdm.component.scss index 64ce774e9..b903ae2e6 100644 --- a/dmestore-ui/src/main/angular/src/app/routes/rdm/rdm.component.scss +++ b/dmestore-ui/src/main/angular/src/app/routes/rdm/rdm.component.scss @@ -211,3 +211,27 @@ input::-ms-clear{ ::ng-deep .datagrid { -ms-overflow-style:scrollbar; } +.noData{ + width: 100%; + height: 400px; + text-align: center; + font-size: 1.6rem; + font-weight: 500; + color: #555555; + display: flex; + flex-flow: column nowrap; + align-content: center; + justify-content: flex-start; + margin-top: 15%; +} +.noDataSvg{ + height: 5rem; + width: 5rem; + background-repeat: no-repeat; + background-size: contain; + background-position: 50%; + background-image: url('noData.svg'); + margin: 0 auto; + margin-bottom: .6rem; +} + diff --git a/dmestore-ui/src/main/angular/src/app/routes/rdm/rdm.component.ts b/dmestore-ui/src/main/angular/src/app/routes/rdm/rdm.component.ts index 5adf28b66..36cf5fbac 100644 --- a/dmestore-ui/src/main/angular/src/app/routes/rdm/rdm.component.ts +++ b/dmestore-ui/src/main/angular/src/app/routes/rdm/rdm.component.ts @@ -5,6 +5,9 @@ import { GlobalsService } from '../../shared/globals.service'; import { ClrWizard, ClrWizardPage } from '@clr/angular'; import { TranslatePipe } from '@ngx-translate/core'; import { getQosCheckTipsTagInfo } from 'app/app.helpers'; +import { isMockData, mockData } from 'mock/mock'; +import { handlerResponseErrorSimple } from './../../app.helpers'; +import { DATASTORE_ON_HOST } from './../../../mock/DATASTORE_ON_HOST'; @Component({ selector: 'app-rdm', @@ -52,6 +55,8 @@ export class RdmComponent implements OnInit { submitLoading = false; rdmSuccess = false; rdmError = false; + //是否查询到DME存储设置 + dmeStrategy=true; // 归属控制器 true 支持 false 不支持 ownershipController = false; @@ -88,7 +93,7 @@ export class RdmComponent implements OnInit { ngOnInit(): void { this.loadStorageDevice(); // this.loadHosts(); - this.tierFresh(); + // this.tierFresh(); const ctx = this.gs.getClientSdk().app.getContextObjects(); console.log(ctx); if (ctx != null) { @@ -103,33 +108,38 @@ export class RdmComponent implements OnInit { // 刷新服务等级列表 tierFresh() { this.tierLoading = true; - this.http.post('servicelevel/listservicelevel', {}).subscribe( - (response: any) => { - this.tierLoading = false; - if (response.code == '200') { - this.serviceLevelsRes = this.recursiveNullDelete(response.data); - this.serviceLevelsRes = this.serviceLevelsRes.filter(item => item.totalCapacity !== 0); - for (const i of this.serviceLevelsRes) { - if (i.totalCapacity == 0) { - i.usedRate = 0.0; - } else { - i.usedRate = ((i.usedCapacity / i.totalCapacity) * 100).toFixed(2); - } - i.usedCapacity = (i.usedCapacity / 1024).toFixed(2); - i.totalCapacity = (i.totalCapacity / 1024).toFixed(2); - i.freeCapacity = (i.freeCapacity / 1024).toFixed(2); + const handlerListservicelevelSuccess = (response: any) => { + this.tierLoading = false; + if (response.code == '200') { + this.serviceLevelsRes = this.recursiveNullDelete(response.data); + this.serviceLevelsRes = this.serviceLevelsRes.filter(item => item.totalCapacity !== 0); + for (const i of this.serviceLevelsRes) { + if (i.totalCapacity == 0) { + i.usedRate = 0.0; + } else { + i.usedRate = ((i.usedCapacity / i.totalCapacity) * 100).toFixed(2); + } + /* i.usedCapacity = (i.usedCapacity / 1024).toFixed(2); + i.totalCapacity = (i.totalCapacity / 1024).toFixed(2); + i.freeCapacity = (i.freeCapacity / 1024).toFixed(2); */ - if (!i.capabilities) { - i.capabilities = {}; - } + if (!i.capabilities) { + i.capabilities = {}; } - this.search(); } - }, - err => { - console.error('ERROR', err); + this.search(); + this.getStorageStrategy() } - ); + }; + + if (isMockData) { + // handlerListservicelevelSuccess(mockData.SERVICELEVEL_LISTSERVICELEVEL); + handlerListservicelevelSuccess({code:'200',data:[]}); + } else { + this.http + .get('servicelevel/listservicelevelByVmfs', {params:{dataStoreId:this.dataStoreObjectId}}) + .subscribe(handlerListservicelevelSuccess, handlerResponseErrorSimple); + } } serviceLevelClick(id: string) { @@ -148,6 +158,32 @@ export class RdmComponent implements OnInit { } } + // 当前服务列表是否有数据 + getStorageStrategy(){ + if (this.serviceLevels.length===0){ + this.dmeStrategy=false; + }else { + this.dmeStrategy=true; + } + } + + //检查第二页是否可以进行下一步 + checkTabs(valid){ + if(this.levelCheck==='storage'){ + return !valid + }else { + if(this.serviceLevels.length===0){ + return valid + }else if(this.serviceLevelId===''){ + return valid + }else { + return !valid + } + } + + + } + submit(): void { if ( this.bandWidthMaxErrTips || @@ -333,43 +369,43 @@ export class RdmComponent implements OnInit { loadDataStore() { this.dsLoading = true; - this.http - .get('v1/vmrdm/vCenter/datastoreOnHost', { params: { vmObjectId: this.vmObjectId } }) - .subscribe( - (result: any) => { - this.dsLoading = false; - let dataStores; - if (result.code === '200') { - dataStores = JSON.parse(result.data); - } else { - dataStores = []; - } - if (dataStores.filter(item => item.vmRootpath).length >= 1) { - const selectData = dataStores.filter(item => item.vmRootpath)[0]; - this.dataStoreObjectId = selectData.objectId; - this.defaultStoreObjectId = selectData.objectId; - } - if (dataStores.length > 0) { - this.dataStores = dataStores.filter(item => !item.vmRootpath); + const handlerDatastoreOnHostSuccess = (result: any) => { + this.dsLoading = false; + let dataStores; + if (result.code === '200') { + dataStores = JSON.parse(result.data); + } else { + dataStores = []; + } + if (dataStores.filter(item => item.vmRootpath).length >= 1) { + const selectData = dataStores.filter(item => item.vmRootpath)[0]; + this.dataStoreObjectId = selectData.objectId; + this.defaultStoreObjectId = selectData.objectId; + } + if (dataStores.length > 0) { + this.dataStores = dataStores.filter(item => !item.vmRootpath); + } else { + this.dataStores = []; + } + if (this.dataStores.length > 0) { + this.dataStores.forEach(item => { + if (item.name.length >= 15) { + item.shortName = item.name.substring(0, 13) + '...'; } else { - this.dataStores = []; - } - if (this.dataStores.length > 0) { - this.dataStores.forEach(item => { - if (item.name.length >= 15) { - item.shortName = item.name.substring(0, 13) + '...'; - } else { - item.shortName = item.name; - } - }); + item.shortName = item.name; } + }); + } - this.cdr.detectChanges(); // 此方法变化检测,异步处理数据都要添加此方法 - }, - err => { - console.error('ERROR', err); - } - ); + this.cdr.detectChanges(); // 此方法变化检测,异步处理数据都要添加此方法 + }; + if (isMockData) { + handlerDatastoreOnHostSuccess(DATASTORE_ON_HOST); + } else { + this.http + .get('v1/vmrdm/vCenter/datastoreOnHost', { params: { vmObjectId: this.vmObjectId } }) + .subscribe(handlerDatastoreOnHostSuccess, handlerResponseErrorSimple); + } } /** @@ -393,6 +429,8 @@ export class RdmComponent implements OnInit { * add 下一页 */ addNextPage() { + // console.log(this.dataStoreObjectId) + this.tierFresh(); this.wizard.next(); } @@ -861,10 +899,10 @@ export class RdmComponent implements OnInit { this.bandwidthLimitErr = bandwidthLimitErr; this.iopsLimitErr = iopsLimitErr; - /* - - - + /* + + + const qosTag = chooseStorage.storageTypeShow.qosTag if (qosTag == 1) { if (this.configModel.flagInfo.minBandwidthChoose && this.configModel.flagInfo.maxBandwidthChoose) { @@ -901,8 +939,8 @@ export class RdmComponent implements OnInit { if (this.configModel.flagInfo.control_policyLower == undefined) { this.bandwidthLimitErr = false; } - - + + */ } } diff --git a/dmestore-ui/src/main/angular/src/app/routes/vmfs/add/add.component.html b/dmestore-ui/src/main/angular/src/app/routes/vmfs/add/add.component.html index 5f1c6808b..d3b5b929c 100644 --- a/dmestore-ui/src/main/angular/src/app/routes/vmfs/add/add.component.html +++ b/dmestore-ui/src/main/angular/src/app/routes/vmfs/add/add.component.html @@ -166,12 +166,13 @@ {{'validations.required' | translate}} - - - - + + + + + + + + + {{'menu.cancel' | translate}} - {{'menu.next' | translate}} + {{'menu.next' | translate}} @@ -225,7 +229,7 @@
- +
@@ -234,7 +238,8 @@ {{item.name}} -
+ + diff --git a/dmestore-ui/src/main/angular/src/app/routes/vmfs/add/add.component.ts b/dmestore-ui/src/main/angular/src/app/routes/vmfs/add/add.component.ts index b00638ce9..b765c7707 100644 --- a/dmestore-ui/src/main/angular/src/app/routes/vmfs/add/add.component.ts +++ b/dmestore-ui/src/main/angular/src/app/routes/vmfs/add/add.component.ts @@ -22,28 +22,42 @@ import { import { ClrWizard, ClrWizardPage } from '@clr/angular'; import { GlobalsService } from '../../../shared/globals.service'; import { - getQosCheckTipsTagInfo, + getQosCheckTipsTagInfo, handlerResponseErrorSimple, isStringLengthByteOutRange, regExpCollection, } from 'app/app.helpers'; import { VmfsCommon } from '../list/VmfsCommon'; +import { isMockData, mockData } from 'mock/mock'; +import { responseVmfsClusterTreeData } from 'mock/vmfsClusterTree'; +import { getLodash } from '@shared/lib'; +import { CommonService } from './../../common.service'; +import { TranslatePipe } from '@ngx-translate/core'; +const _ = getLodash(); @Component({ selector: 'app-list', templateUrl: './add.component.html', styleUrls: ['./add.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, - providers: [AddService], + providers: [AddService, CommonService, TranslatePipe], }) export class AddComponent extends VmfsCommon implements OnInit { constructor( - private remoteSrv: AddService, + private commonService: CommonService, + private remoteService: AddService, private route: ActivatedRoute, public cdr: ChangeDetectorRef, private router: Router, private globalsService: GlobalsService ) { super(); + // 设置主机/集群 + this.setDeviceList_new(this, async () => { + await this.setHostDatas_new(); + // 此方法变化检测,异步处理数据都要添加此方法 + this.cdr.detectChanges(); + }); + // this.setDeviceList(); this.form.version = '5'; // 版本 this.setFormValueWhenHiden(false); } @@ -60,9 +74,13 @@ export class AddComponent extends VmfsCommon implements OnInit { srgOptions = []; // 主机AND集群 deviceList: HostOrCluster[] = []; + deviceList_list: HostOrCluster[] = []; // 已选择的主机/集群 chooseDevice; + //添加操作返回的数据 + partSuccessData; + // 服务等级列表 serviceLevelList: ServiceLevelList[] = []; workloads: Workload[] = []; // Workload @@ -160,9 +178,6 @@ export class AddComponent extends VmfsCommon implements OnInit { // 版本、块大小、粒度下拉框初始化 this.setBlockSizeOptions(); - // 设置主机/集群 - this.setDeviceList(); - // 初始化服务等级数据 this.setServiceLevelList(); @@ -269,7 +284,7 @@ export class AddComponent extends VmfsCommon implements OnInit { // 设置主机数据 setHostDatas() { return new Promise((resolve, reject) => { - this.remoteSrv.getHostList().subscribe((result: any) => { + const handlerSetHostDataSuccess = (result: any) => { let hostList: HostList[] = []; // 主机列表 console.log('host', result); if (result.code === '200' && result.data !== null) { @@ -286,14 +301,44 @@ export class AddComponent extends VmfsCommon implements OnInit { this.form.hostDataloadSuccess = true; resolve(this.deviceList); this.cdr.detectChanges(); // 此方法变化检测,异步处理数据都要添加此方法 - }); + }; + + if (isMockData) { + handlerSetHostDataSuccess(responseVmfsClusterTreeData); + } else { + this.remoteService.getHostList().subscribe(handlerSetHostDataSuccess); + } + }); + } + setHostDatas_new() { + return new Promise((resolve, reject) => { + const handlerSetHostDataSuccess = (result: any) => { + console.log('host', result); + if (result.code === '200' && result.data !== null) { + this.deviceList_list = _.map(result.data, item => { + return { + clusterId: item.hostId, + clusterName: item.hostName, + deviceType: 'host', + }; + }); + } + this.form.hostDataloadSuccess = true; + resolve(this.deviceList_list); + }; + + if (isMockData) { + handlerSetHostDataSuccess(mockData.ACCESSVMWARE_LISTHOST); + } else { + this.remoteService.getHostList().subscribe(handlerSetHostDataSuccess, reject); + } }); } // 设置集群数据 setClusterDatas() { return new Promise((resolve, reject) => { - this.remoteSrv.getClusterList().subscribe((result: any) => { + this.remoteService.getClusterList().subscribe((result: any) => { let clusterList: ClusterList[] = []; // 集群列表 console.log('cluster', result); console.log('cluster', result.data !== null); @@ -321,16 +366,22 @@ export class AddComponent extends VmfsCommon implements OnInit { // 初始化服务等级选择参数 this.serviceLevelIsNull = false; // 获取服务等级数据 - this.remoteSrv.getServiceLevelList().subscribe((result: any) => { - console.log(result); + const HandlerGetServiceLeveListSuccess = (result: any) => { if (result.code === '200' && result.data !== null) { this.serviceLevelList = result.data.filter(item => item.totalCapacity !== 0); - console.log('this.serviceLevelList', this.serviceLevelList); } + // 隐藏loading this.modalLoading = false; - // this.globalsService.loading = false; + // this.gs.loading = false; this.cdr.detectChanges(); // 此方法变化检测,异步处理数据都要添加此方法 - }); + }; + if (isMockData) { + HandlerGetServiceLeveListSuccess(mockData.SERVICELEVEL_LISTSERVICELEVEL); + } else { + this.remoteService + .getServiceLevelList() + .subscribe(HandlerGetServiceLeveListSuccess, handlerResponseErrorSimple); + } } // 选择服务等级时 @@ -396,7 +447,7 @@ export class AddComponent extends VmfsCommon implements OnInit { this.cdr.detectChanges(); // 此方法变化检测,异步处理数据都要添加此方法 }; - this.remoteSrv.getStorages().subscribe(handlerGetStorageListSuccess); + this.remoteService.getStorages().subscribe(handlerGetStorageListSuccess); } // 获取存储池数据 @@ -432,7 +483,7 @@ export class AddComponent extends VmfsCommon implements OnInit { } // 获取存储池数据 // if (!storagePoolList) { - this.remoteSrv + this.remoteService .getStoragePoolsByStorId(this.form.storage_id, mediaType) .subscribe((result: any) => { console.log('storagePools', result); @@ -454,7 +505,7 @@ export class AddComponent extends VmfsCommon implements OnInit { // } // 获取workLoad if (this.showWorkLoadFlag) { - this.remoteSrv.getWorkLoads(this.form.storage_id).subscribe((result: any) => { + this.remoteService.getWorkLoads(this.form.storage_id).subscribe((result: any) => { console.log('storagePools', result); if (result.code === '200' && result.data !== null) { this.workloads = result.data; @@ -486,7 +537,7 @@ export class AddComponent extends VmfsCommon implements OnInit { } // 添加vmfs 处理 - addVmfsHanlde() { + async addVmfsHanlde() { if ( this.bandWidthMaxErrTips || this.iopsMaxErrTips || @@ -531,15 +582,29 @@ export class AddComponent extends VmfsCommon implements OnInit { // 默认GB 不变 break; } + // 主机/集群数据处理 - if (this.chooseDevice.deviceType === 'host') { + this.chooseDevice = this.addForm.chooseDevice; + /* 630修改 不需要区分集群和主机 */ + /* if (this.chooseDevice.deviceType === 'host') { + addSubmitForm.host = this.chooseDevice.deviceName; + addSubmitForm.hostId = this.chooseDevice.deviceId; + } else { + addSubmitForm.cluster = this.chooseDevice.deviceName; + addSubmitForm.clusterId = this.chooseDevice.deviceId; + } */ + + // 主机/集群数据处理 + /* if (this.chooseDevice.deviceType === 'host') { addSubmitForm.host = this.chooseDevice.deviceName; addSubmitForm.hostId = this.chooseDevice.deviceId; } else { addSubmitForm.cluster = this.chooseDevice.deviceName; addSubmitForm.clusterId = this.chooseDevice.deviceId; } - if (this.levelCheck === 'customer') { + */ if ( + this.levelCheck === 'customer' + ) { // 未选择 服务等级 需要将服务等级数据设置为空 addSubmitForm.service_level_id = null; addSubmitForm.service_level_name = null; @@ -577,12 +642,22 @@ export class AddComponent extends VmfsCommon implements OnInit { // 打开 loading // this.globalsService.loading = true; this.modalHandleLoading = true; - this.remoteSrv.createVmfs(addSubmitForm).subscribe((result: any) => { + const params = _.merge( + { + chooseDevice: this.chooseDevice, + }, + addSubmitForm + ); + const handlerCreateVmfsSuccess = (result: any) => { this.modalHandleLoading = false; if (result.code === '200') { console.log('创建成功'); // 打开成功提示窗口 this.addSuccessShow = true; + }else if(result.code==='206'){ + // this.wizard.close(); + this.isOperationErr=true; + this.partSuccessData=result } else if (result.code === '-60001') { this.connectivityFailure = true; this.showDetail = false; @@ -602,10 +677,15 @@ export class AddComponent extends VmfsCommon implements OnInit { } else { console.log('创建失败:' + result.description); // 失败信息 + this.partSuccessData=result; this.isOperationErr = true; } this.cdr.detectChanges(); // 此方法变化检测,异步处理数据都要添加此方法 - }); + }; + + const res = await this.commonService.remoteCreateVmfs(params); + handlerCreateVmfsSuccess(res); + // this.remoteSrv.createVmfs(addSubmitForm).subscribe(handlerCreateVmfsSuccess); } else { this.serviceLevelIsNull = true; } @@ -940,7 +1020,7 @@ export class AddComponent extends VmfsCommon implements OnInit { (this as any).checkVmfsNameExist_oldName = name; this.modalHandleLoading = true; - this.remoteSrv.checkVmfsName(name).subscribe((result: any) => { + this.remoteService.checkVmfsName(name).subscribe((result: any) => { this.modalHandleLoading = false; if (result.code === '200') { // result.data true 不重复 false 重复 @@ -968,7 +1048,7 @@ export class AddComponent extends VmfsCommon implements OnInit { (this as any).checkVolNameExist_oldName = name; this.modalHandleLoading = true; // 校验VMFS名称重复 - this.remoteSrv.checkVolName(name).subscribe((result: any) => { + this.remoteService.checkVolName(name).subscribe((result: any) => { this.modalHandleLoading = false; if (result.code === '200') { // result.data true 不重复 false 重复 @@ -1357,10 +1437,10 @@ export class AddComponent extends VmfsCommon implements OnInit { this.bandwidthLimitErr = bandwidthLimitErr; this.iopsLimitErr = iopsLimitErr; - /* - - - + /* + + + const qosTag = chooseStorage.storageTypeShow.qosTag; if (qosTag == 1) { if (this.form.minbandwidthChoose && this.form.maxbandwidthChoose) { @@ -1405,7 +1485,7 @@ export class AddComponent extends VmfsCommon implements OnInit { if (this.form.control_policyLower == undefined) { this.bandwidthLimitErr = false; } - + */ } } diff --git a/dmestore-ui/src/main/angular/src/app/routes/vmfs/add/add.service.ts b/dmestore-ui/src/main/angular/src/app/routes/vmfs/add/add.service.ts index f4afbbd76..99e727b19 100644 --- a/dmestore-ui/src/main/angular/src/app/routes/vmfs/add/add.service.ts +++ b/dmestore-ui/src/main/angular/src/app/routes/vmfs/add/add.service.ts @@ -4,6 +4,7 @@ import { HttpClient } from '@angular/common/http'; @Injectable() export class AddService { constructor(private http: HttpClient) {} + // 获取所有的主机 getHostList() { return this.http.get('accessvmware/listhost'); @@ -24,7 +25,9 @@ export class AddService { } // 通过存储ID获取存储池数据 (vmfs添加mediaType为block) getStoragePoolsByStorId(storageId: string, mediaType: string) { - return this.http.get('dmestorage/storagepools?storageId='+ storageId + '&mediaType=' + mediaType); + return this.http.get( + 'dmestorage/storagepools?storageId=' + storageId + '&mediaType=' + mediaType + ); } /** diff --git a/dmestore-ui/src/main/angular/src/app/routes/vmfs/delete/delete.component.html b/dmestore-ui/src/main/angular/src/app/routes/vmfs/delete/delete.component.html index 799b7cd3e..ea2eb1f79 100644 --- a/dmestore-ui/src/main/angular/src/app/routes/vmfs/delete/delete.component.html +++ b/dmestore-ui/src/main/angular/src/app/routes/vmfs/delete/delete.component.html @@ -6,6 +6,7 @@
{{'errorMsg.deleteError' | translate}}
+
{{'vmfs.del.warning'|translate}}

{{'vmfs.del.content' | translate}}

- +
- - {{'vmfs.datastoreSetting' | translate}} - + -->
@@ -429,7 +428,8 @@ {{'vmfs.capacityTips' | translate}} - {{'validations.required' | translate}}:{{'vmfs.capacityTips' | translate}} + {{'validations.required' | translate}}:{{'vmfs.capacityTips' | translate}} + @@ -453,8 +453,10 @@ - @@ -462,6 +464,20 @@ + + + + + + + + + + + {{'menu.cancel' | translate}} @@ -530,8 +547,8 @@ {{'errorMsg.addError' | translate}} --> -
- +
+
@@ -541,8 +558,8 @@ style="height: 50px; line-height: 50px;color: #333;font-size:16px;">{{item.name}} - -
+ + @@ -1124,17 +1141,18 @@ +
+ + {{'vmfs.loadingTips' | translate}} + +
+ + + +
+ + {{'vmfs.loadingTips' | translate}} + +